Seja no deploy de uma aplicação desktop com instalação local, uma aplicação web ou um aplicativo mobile, precisamos nos certificar de algumas coisas. Primeiro, é necessário que os ambientes de desenvolvimento e de produção estejam totalmente compatíveis, tendo as mesmas configurações e versões de linguagem, bibliotecas e Sistema Operacional, dentre outras dependências do projeto. Por último, devemos nos certificar de que todas as configurações da aplicação estão adequadas para produção: se a aplicação consome um banco de dados, precisamos apontá-la para o banco de dados de produção, se consome uma API, devemos apontá-la para a API de produção também, etc.

O próprio deploy também pode ser um ponto de falha, pelos motivos citados anteriormente, e, por isso, devemos nos cercar de todos os tipos de testes, bem como automatizar o máximo possível desse processo. Alguns serviços de Cloud fornecem soluções prontas-para-uso que permitem a automatização do deploy com pouca ou nenhuma configuração. Um desses serviços é o Heroku, uma das plataformas de execução de aplicações em Cloud mais simples e comuns do mercado.

Nesse artigo veremos como realizar o deploy no Heroku de uma aplicação construída com o Angular. Utilizaremos as ferramentas de build do próprio Angular CLI para gerar os arquivos finais da nossa aplicação, bem como o Heroku CLI para a criação e envio da aplicação para o Heroku. Ao final do processo seremos capazes de realizar alterações na aplicação em produção apenas dando o PUSH das modificações para um repositório GIT disponibilizado pelo Heroku. Não se preocupe, utilizaremos o plano gratuito.

Faremos o deploy da aplicação desenvolvida no projeto App Fullstack com cadastro/login em Node e Angular . Se preferir, pode criar uma aplicação do zero utilizando o Angular CLI, basta acompanhar o passo a passo que demos no curso Angular: Conectando com uma API RESTful.

Servidor web com Node.js + Express

Uma aplicação Angular, após o build, consiste de um arquivo index.html e alguns arquivos .js e .css, nada mais. Se dermos um duplo clique nesse arquivo .html, veremos nossa aplicação funcionando perfeitamente no navegador.

Entretanto, para que possamos disponibilizá-la como uma aplicação web, precisaremos de um servidor que seja capaz de receber requisições HTTP e enviar os arquivos da aplicação, uma vez que forem requisitados. Como estamos falando de uma página estática (os arquivos não são gerados a cada requisição, apenas servidos ao navegador do usuário), poderíamos utilizar até o mesmo o GitHub Pages.

Poderíamos optar por um servidor HTTP como o Apache e Nginx, mas também pode ser uma pequena aplicação Node.js. Neste artigo seguiremos essa abordagem e criaremos um pequeno servidor HTTP utilizando o Node.js e o framework Express. Esse servidor HTTP terá uma única função: ao receber uma requisição deve fornecer os arquivos estáticos da aplicação.

Utilizaremos o NPM para instalar o Express. Para isso, abra o terminal e, no diretório do projeto, execute o seguinte comando:

npm install express --save

Obs: O parâmetro --save salvará o nome e versão do Express no arquivo package.json. Isso será necessário para que, mais adiante, o Heroku saiba quais dependências deve instalar para que a aplicação funcione corretamente.

No diretório raiz da nossa aplicação, no mesmo nível que o arquivo package.json, criaremos o nosso servidor em um arquivo chamado server.js:

const express = require('express');
const path = require('path');
const nomeApp = process.env.npm_package_name;
const app = express();

app.use(express.static(`${__dirname}/dist/${nomeApp}`));

app.get('/*', (req, res) => {
res.sendFile(path.join(`${__dirname}/dist/${nomeApp}/index.html`));
});

app.listen(process.env.PORT || 8080);
  • Linhas 1 e 2: Importamos o Express instalado anteriormente e o modulo Path do Node.js.
    const express = require('express');
    const path = require('path');
  • Linhas 3 e 4: Ao iniciar uma aplicação utilizando o NPM, teremos disponíveis variáveis de ambiente que nos permitem acessar dados do arquivo package.json. Utilizaremos esse recurso para obter o nome do pacote, pois, ao construir a aplicação, o Angular CLI irá disponibilizar os arquivos desta no diretório /dist/nome-do-pacote. Criamos, também, uma instância do Express.
    const nomeApp = process.env.npm_package_name;
    const app = express();
  • Linhas 7 e 10: Disponibilizamos todos os arquivos estáticos gerados ao construir a aplicação, bem como uma rota que responderá com o arquivo index.html para qualquer requisição GET.
    app.use(express.static(`${__dirname}/dist/${nomeApp}`));
    
    app.get('/*', (req, res) => {
    res.sendFile(path.join(`${__dirname}/dist/${nomeApp}/index.html`));
    });
  • Linha 12: Iniciamos o servidor escutando na porta da variável de ambiente PORT disponibilizada pelo Heroku ou, caso esta não esteja definida, na porta 8080 para que possamos executá-la localmente.
    app.listen(process.env.PORT || 8080);

Modificando o package.json

Agora que temos nosso servidor pronto, precisamos modificar o package.json para adicionar algumas informações importantes para o Heroku, tais como a forma que a aplicação deve ser construída e iniciada.

Uma vez que o Heroku inicia a aplicação através do comando npm start devemos, no atributo scripts do nosso package.json, especificar a forma que a aplicação deve ser executada. Além disso, criaremos um novo script chamado postinstall, que será executado assim que todas as dependências forem instaladas. Esse script é necessário para que possamos construir o pacote final da nossa aplicação e disponibilizá-la no diretório /dist/nome-do-pacote.

Por fim, no mesmo arquivo, criaremos um atributo chamado engines que receberá as versões do Node.js e do NPM que devem ser utilizadas pelo Heroku. É recomendado utilizar em produção as mesmas versões que foram utilizadas no desenvolvimento e podemos obtê-las através dos comandos npm -v e node -v.

{
 "name": "nome-do-pacote",
 ...
 "scripts": {
   ...
   "start": "node server.js",
   "postinstall": "ng build --aot --prod"
 },
 ...
 "engines": {
   "node": "10.13.0",
   "npm": "6.4.1"
 }
}
Obs: Os parâmetros --aot e --prod permitem, respectivamente, a construção Ahead of Time (a frente do tempo) e a utilização das configurações de produção como, por exemplo, as variáveis especificadas no arquivo environments.prod.ts da aplicação.

Executando a aplicação Angular no Heroku

Nessa etapa do artigo criaremos uma instância no Heroku e enviaremos os arquivos da nossa aplicação para o repositório disponibilizado pelo mesmo. Lembre-se: você deve possuir uma conta no Heroku, o Heroku CLI e o GIT instalados na sua máquina.

No diretório raiz da aplicação, a partir do Heroku CLI, utilizaremos o seguinte comando para criar a instância onde será executada nosso pequeno servidor Node.js:

heroku create

Ao final da execução, o Heroku terá criado um endereço aleatório para a nossa aplicação e um repositório GIT para onde enviaremos os arquivos da mesma.

Creating app... done, ⬢ fast-citadel-90247
https://fast-citadel-90247.herokuapp.com/ | https://git.heroku.com/fast-citadel-90247.git

Feito isso, podemos commitar todos os arquivos da nossa aplicação e realizar o push para o branch Master do repositório criado anteriormente. Esse repositório pode ser utilizado da mesma forma que qualquer outro repositório Git remoto, como o GitHub e Bitbucket, por exemplo, mas o Heroku só reconstruirá a aplicação caso o commit seja realizado no branch Master:

git add . 
git commit -m ":rocket: Meu primeiro deploy no Heroku!"
git push heroku master

Dado que o Heroku ficará responsável por instalar todas as dependências, construir a aplicação e executar o servidor, pode ser que a execução do comando acima dure alguns minutos. Quando o mesmo terminar, seremos capazes de acessar nossa aplicação através do endereço informado pelo Heroku, assim como pode ser visto na barra de navegação na Figura 1.

Aplicação Angular funcionando no Heroku
Figura 1. Aplicação Angular funcionando no Heroku

Gostou do assunto e está interessado a aprender mais sobre Angular? Deixe um joinha! Tem uma opinião sobre o Heroku ou outros servidores Cloud? Deixe nos comentários, estamos loucos para saber sobre a experiência de vocês ;)