Introdução

Você deve estar pensando - “WTF??? Outro Framework JavaScript???” - sim, sim. Porém o Aurelia me chamou a atenção por causa de alguns pontos, entre eles:

Tem mais alguns pontos que me chamou a atenção, mas nesse primeiro momento vamos manter o básico. Esse é o primeiro artigo de uma série de artigos em que irei mostrar como podemos trabalhar com o Aurelia, e a partir daí você poderá decidir se vai continuar usando ele ou não. De toda maneira, conhecimento nunca é demais então vamos começar a aprender em como trabalhar com o Aurelia!

Configurando seu projeto

Nesse primeiro post vamos construir uma pequena e simples aplicação, apenas para explicar alguns conceitos básicos do Aurelia e como iniciar um projeto do zero com ele. Para continuar você precisa ter o Node na versão 4 ou mais atual (caso não tenha, instale ele antes de continuar).

Agora vamos baixar o CLI oficial do Aurelia:

npm i -g aurelia-cli

Acesse o diretório que deseja criar a aplicação pela linha de comando e execute o comando a seguir para criar uma nova aplicação Aurelia:

au new

Agora você irá responder algumas questões que o CLI irá te fazer:

Please enter a name for your new project below.
# Digite aurelia-first-app

Would you like to use the default setup or customize your choices?
# Digite 3 para customizar a nossa aplicação

What transpiler would you like to use?
# Apenas digite enter, usaremos Babel para essa série de artigos

What css processor would you like to use?
# Digite 4, usaremos o Stylus para essa série de artigos

Would you like to configure unit testing?
# Apenas digite enter, não iremos criar testes agora pois estamos criando apenas uma aplicação inicial para entender como o Aurelia funciona, mas é uma boa prática sempre fazer testes, então já deixe o projeto configurado para testes

What is your default code editor?
# Digite o número referente ao editor que estiver usando, caso não seja nenhum desses apenas digite enter

Would you like to create this project?
# Confira as opções apresentadas e caso esteja correto apenas digite enter

Would you like to install the project dependencies?
# Apenas digite enter para instalar as dependências

Aguarde as dependências serem instaladas e acesse o diretório de sua aplicação:

cd aurelia-first-app

O CLI do Aurelia nos fornece alguns comandos para ajudar no desenvolvimento de nossa aplicação, entre eles:

au run
au run --watch
au test
au test --watch
au build --env prod
au help

Para garantir que tudo ocorreu bem execute o comando au run para ver sua aplicação executando e acesse: http://localhost:9000 em seu browser. Você deve ver apenas um título: “Hello World!” que indicará que o projeto está executando com sucesso.

Entendendo sua aplicação Aurelia

Agora que temos nosso projeto configurado e executando normalmente, vamos entender a estrutura de nossa aplicação e aprender um pouco mais sobre uma aplicação Aurelia!

Estrutura de diretórios

A estrutura de diretórios padrão que vem quando iniciamos um projeto é bem simples e muitos dos diretórios e arquivos são comuns em outras aplicações. Temos cinco diretórios:

Além desses diretórios temos diversos arquivos como o .babelrc, .editorconfig, package.json, etc. Todos esses arquivos não são específicos do Aurelia e você já deve conhecer todos, ou pelo menos a maioria deles.

Nosso foco nesse artigo será o arquivo index.html e os arquivos dentro do diretório src. Então vamos lá!!!

O arquivo index.html

Ao abrir o arquivo index.html você verá que ele é um arquivo extremamente simples. Nesse arquivo temos poucas coisas para explicar:

Na tag body temos um atributo aurelia-app="main", esse atributo é usado para indicarmos o nome de nossa aplicação e também indicar para o Aurelia qual é o arquivo principal de nossa aplicação. Quando iniciar o Aurelia irá procurar um arquivo dentro do diretório src com o mesmo nome passado para o atributo aurelia-app.

Temos uma tag script que carrega o vendor-bundle.jsque possui todo código necessário para nossa aplicação executar sem problemas e temos um atributo data-main="aurelia-bootstrapper". O aurelia-bootstrapper é um módulo que irá procurar por atributos do Aurelia (por exemplo o atributo aurelia-app na tag body) e interpretar esses atributos.

O diretório src

Quando olhamos esse diretório, nos deparamos com alguns arquivos .js, um diretório resources (que vamos explicar daqui a pouco) e um arquivo .html.

O arquivo main.js

Como falado anteriormente, o Aurelia irá buscar nesse diretório um arquivo com mesmo nome passado para o atributo aurelia-app que no nosso caso é o arquivo main.js. Esse arquivo é o ponto de partida de nossa aplicação, ou seja, onde vamos configurar nossa aplicação. Ao abrir esse arquivo vemos que ele realmente apenas cuida de fazer configurações de nossa aplicação e iniciar ela.

import environment from './environment';

//Configure Bluebird Promises.
Promise.config({
  longStackTraces: environment.debug,
  warnings: {
    wForgottenReturn: false
  }
});

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .feature('resources');

  if (environment.debug) {
    aurelia.use.developmentLogging();
  }

  if (environment.testing) {
    aurelia.use.plugin('aurelia-testing');
  }

  aurelia.start().then(() => aurelia.setRoot());
}

A primeira linha desse arquivo está fazendo um import de um objeto chamado environment do nosso arquivo environment.js, vamos abrir esse arquivo e entender o que ele faz.

Ao abrir o arquivo environment.js vemos que ele apenas define um objeto com dois atributos: debug e testing. No Aurelia podemos habilitar e desabilitar algumas funcionalidades de acordo com nossa necessidade. Por exemplo, podemos habilitar o debug quando estivermos em desenvolvimento e desabilitar ele ao enviar a aplicação para produção. Como estamos em desenvolvimento iremos deixar ambos habilitados.

Voltando ao nosso arquivo main.js, o próximo código em nosso arquivo é a configuração de nossas Promises, por padrão o Aurelia utiliza o Bluebird para cuidar das Promises:

//Configure Bluebird Promises.
Promise.config({
  longStackTraces: environment.debug,
  warnings: {
    wForgottenReturn: false
  }
});

Aqui usamos o atributo debug do arquivo environment.js para definir se iremos habilitar um Stack Trace completo. O atributo wForgottenReturn é usado para emitir um warning caso algum return seja esquecido no código.

Depois de configurar as Promises, temos a configuração da nossa aplicação Aurelia dentro da função configure. No começo da função, dizemos ao Aurelia para usar uma configuração padrão e definimos o nosso diretório resources como uma feature:

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .feature('resources');

Mas você deve estar se perguntando, WTF is a FEATURE?!?!?!. Muito bem, vamos entender agora.

Aurelia Features

O Aurelia permite que reutilizemos código através da funcionalidade feature, que nada mais é que um grupo de componentes ou funcionalidades que juntas se tornam uma feature. Dessa maneira podemos utilizar nossas features em todos outros componentes que criarmos em nossa aplicação.

Por padrão, ao criar um projeto pelo CLI do Aurelia, ele já nos disponibiliza uma feature chamada resources que como o nome diz são recursos que podemos reutilizar em toda nossa aplicação. Ao abrir o diretório src/resources, nos deparamos com um arquivo index.js que é obrigatório ao criar uma nova feature e vemos quatro diretórios, cada um deles é referente a uma funcionalidade que o Aurelia possui, vamos agora entender o que é cada uma delas:

// square-panel.js
export class SquarePanelCustomAttribute {
  static inject = [Element];

  constructor(element){
    this.element = element;
    this.element.style.width = this.element.style.height = '150px';
    this.element.style.border = '2px solid #000';
    this.element.style.padding = '10px';
  }
}
<template>
  <require from="./square-panel"></require>
  <div square-panel></div>
</template>

OBS: O nome do Custom Attribute deve seguir a convenção utilizada pelo Aurelia que é utilizar NOME DO ATRIBUTO + CustomAttribute (todas iniciais em maiúsculo) para o nome da classe no JavaScript e usar ela no HTML com nome todo em minúsculo e separado por -. No nosso exemplo a classe SquarePanelCustomAttribute é usada através do atributo square-panel.

  // hello-world.html
  <template bindable="greeting, fullName">
    ${greeting} ${fullName}
  </template>
  
  // app.html
  <template>
    <require from="./hello-world.html"></require>
    <hello-world greeting="Hello" full-name="Aurelia Framework"></hello-world>
  </template>
  
  // hello-world.js
  export class HelloWorldCustomElement {
    greeting = 'Hello Aurelia Framework!';
  }
  
  // hello-world.html
  <template>
    ${greeting}
  </template>
  
  // app.html
  <template>
    <require from="./hello-world"></require>
    <hello-world></hello-world>
  </template>
  
// format-date.js
import moment from 'moment';

export class FormatDateValueConverter  {
  toView(value) {
    return moment(value).format('D/M/YYYY');
  }
}
// converter-test.js
export class ConverterTest {
  constructor() {
    this.currentDate = newDate();
  }
}
// converter-test.html
<template>
  <require from="./format-date"></require>
  ${currentDate | formatDate}
</template>

Voltando ao arquivo main.js

Depois de aprendermos bastante sobre alguns recursos do Aurelia, vamos continuar a explicar o nosso arquivo main.js. Logo após configurar o diretório resources como uma feature vemos dois ifs:

if (environment.debug) {
  aurelia.use.developmentLogging();
}

if (environment.testing) {
  aurelia.use.plugin('aurelia-testing');
}

O primeiro if verifica se o debug está ativado em nosso environment.js e caso esteja ele ativa os logs de desenvolvimento, que são logs detalhados do que acontece em nossa aplicação, já o segundo if verifica se o testing está ativado em nosso environment.js e caso esteja ele ativa o plugin aurelia-testing que é usado para executar testes em nossa aplicação.

Por último e não menos importante temos a seguinte linha de código:

aurelia.start().then(() => aurelia.setRoot());

Essa linha chama o método start que é o que inicia o Aurelia e retorna uma Promise, depois de retornada, o Framework está pronto para iniciar (todos plugins, bibliotecas, etc foram carregados) e agora podemos indicar o ponto inicial para nossa aplicação com o método setRoot. Caso não seja passado nenhum parâmetro para essa função ela assume que o elemento DOM que vai ser usado pela sua aplicação é o elemento com o atributo aurelia-app no arquivo index.html e que o Componente Pai/Componente Raiz da sua aplicação é o componente app.js/app.html. Caso queira customizar, basta passar os parâmetros como no código abaixo:

aurelia.start().then(() => aurelia.setRoot('awesome-app', document.getElementById('my-app')));

O código acima faz com que o elemento com o atributo id="my-app" seja o elemento DOM que será usado pela sua aplicação e que o componente awesome-app.js/awesome-app.html seja o Componente Pai/Componente Raiz da sua aplicação.

O componente app

Depois de aprender como uma aplicação Aurelia realmente funciona, vamos ver agora como trabalhar com componentes em nossa aplicação. Por padrão o CLI cria um componente app que é composto por uma View: app.html e um Model: app.js. Vamos abrir o arquivo app.js, nele temos o seguinte código:

export class App {
  constructor() {
    this.message = 'Hello World!';
  }
}

Podemos ver que é um arquivo extremamente simples, aqui temos apenas a criação de uma classe que na hora que está sendo criada define um atributo message que será usado pela View.

Agora ao abrir o arquivo app.html vemos o seguinte código:

<template>
  <h1>${message}</h1>
</template>

Essa é a View do componente app e a única coisa que ela faz é imprimir um título com o valor do atributo message do Model. Extremamente simples não é?

Que tal agora brincarmos um pouco com o código e fazer um simples exemplo com algumas coisas que aprendemos até aqui? Vamos lá?!?!?

Sua primeira aplicação

Agora que você já sabe como o Aurelia funciona, já conhece muitos dos seus recursos, que tal juntar esse conhecimento e fazer sua primeira aplicação com ele hein?!?!?

Vamos fazer uma simples aplicação para mostrar uma mensagem, mas criando um Custom Element, um Custom Attribute e um Value Converter e adicionando eles ao nosso app.html;

Criando o Value Converter

Dentro do diretório src/resources/value-converters crie um arquivo chamado capitalize-words.js. Nesse arquivo coloque o seguinte código:

export class CapitalizeWordsValueConverter  {
  toView(value) {
    return value.replace(/\b\w/g, l => l.toUpperCase());
  }
}

Esse Value Converter será responsável por fazer com que a primeira letra de cada palavra na string passada seja transformada para maiúscula (capitalizada). Viu como é fácil criar um Value Converter??? Agora vamos criar nosso Custom Attribute.

Criando o Custom Attribute

Dentro do diretório src/resources/attributes crie um arquivo chamado primary-text.js. Nesse arquivo coloque o seguinte código:

export class PrimaryTextCustomAttribute {
  static inject = [Element];

  constructor(element) {
    this.element = element;
    this.element.style.color = 'red';
    this.element.style.fontFamily = 'Verdana, sans-serif';
    this.element.style.fontSize = '26px';
    this.element.style.fontWeight = 'bolder';
  }
}

Esse Custom Attribute será responsável por estilizar o texto de nosso Custom Element que será criado a seguir.

Criando o Custom Element

Dentro do diretório src/resources/elements crie um diretório chamado greeting-message e dentro desse diretório crie os arquivos: greeting-message.js e greeting-message.html.

No arquivo greeting-message.js coloque o seguinte código:

export class GreetingMessageCustomElement {
  constructor() {
    this.greeting = 'hello aurelia framework!';
  }
}

No arquivo greeting-message.html coloque o seguinte código:

<template>
  <require from="../../attributes/primary-text"></require>
  <require from="../../value-converters/capitalize-words"></require>
  <h1 primary-text>${greeting | capitalizeWords}</h1>
</template>

Esse Custom Element apresenta um título na página utilizando o Value Converter e o Custom Attribute criados anteriormente. Agora vamos usar o Custom Element criado em nossa aplicação.

Utilizando o componente criado

Para usar nosso Custom Element, devemos inserir ele em nosso arquivo app.html, então abra esse arquivo e deixe ele como o código abaixo:

<template>
  <require from="./resources/elements/greeting-message/greeting-message"></require>
  <greeting-message></greeting-message>
</template>

Dessa forma estaremos utilizando agora o nosso componente criado e podemos alterar o nosso app.js para conter apenas o código:

export class App {}

Conclusão

Agora salve os arquivos, vá até a pasta aurelia-first-app pela linha de comando e execute o comando au run para executar sua aplicação. Vá até http://localhost:9000 e você irá ver sua aplicação executando!!! Nesse momento você deverá ver a mensagem Hello Aurelia Framework! com as palavras capitalizadas, na cor vermelha e em negrito, mostrando assim que seu componente greeting-message está usando o Custom Attribute e o Value Converter que criamos!!!

Pronto, você agora sabe como o Aurelia funciona e já criou sua primeira aplicação com ele!!! Fique ligado pois esse é só o primeiro post dessa série de artigos sobre esse Framework, nos próximos artigos vamos criar uma aplicação mais complexa com o Aurelia!!!

Você pode conferir o código desse artigo por esse link!!!

Espero que tenham gostado e até o próximo artigo!!! Abraços!!!