Angular Universal

Server side rendering já é realidade

> Blog > Tutorial Angular Universal - Server side rendering já é realidade

Finalmente é possível realizar o tão aguardado Server Side Rendering com Angular. Confesso a vocês que venho tentado sem sucesso colocar aplicações em produção com Universal.

O grande problema sempre foi a questão do angular-cli não ser totalmente integrado com Universal, nos exigindo a criação de um grande "boilerplate" pra poder executar qualquer exemplo, mas esta realidade mudou a poucos dias com os últimos commits que a galera do universal subiu.

Agora de fato é mais vantajoso utilizar Server Side Rendering com angular em conjunto com a linha de comando, pois torna a aplicação completamente visível para os bots uma vez que o resultado no browser é todo o html renderizado.

O que é SSR?

Quando trabalhamos com aplicações web modernas, precisamos considerar 3 aspectos:

  1. Conteúdo
  2. Estilo
  3. Estado

Por padrão os frameworks frontend possuem uma arvore de objetos DOM virtual, então quando um bot tenta acessar o conteúdo da aplicação, como ele não é capaz de executar seu código javascript, não conseguirá entender o conteúdo da página.

Gerando um resultado como este

angular sem server side rendering

Este não é um problema para os usuários, pois o browser sim é capaz de executar sua aplicação javascript renderizando conteúdo, estilos e estados.

Como resolver esta questão

Até então pra quem trabalha com Angular e algumas outras frameworks javascript, a solução era "pre renderizar" todo o conteúdo da aplicação através um de carinha bem interessante chamado Prerender.io. Não vou entrar em muitos detalhes, mas este camarada usa basicamente o Phantom.js pra simular um navegador e renderizar suas páginas, fazendo cache do resultado no serviço da amazon S3.

Confesso que venho utilizado largamente este esquema, inclusive com uma cloud própria na amazon, mas devido as últimas novidades em relação ao Universal, já estou migrando todas minhas aplicações para SSR.

Novidade: Em meu curso avançado de angular, ensinarei o passo a passo de como refatorar e fazer deploy da Super Store na amazon utilizando Server Side Rendering

Porque utilizar o Universal

O primeiro ganho em relação ao prerender.io é em relação a custo. Você não precisará pagar nenhum servidor extra pra poder resolver este tipo de problema. No mesmo servidor que está servindo sua aplicação de maneira estática, ocorrerá a renderização do conteúdo, em tempo real.

O segundo ganho é que mesmo utilizando o prerender, você ainda precisaria criar novas soluções pra agilizar o processo de cache, pois os processos do phantom.js são pesados e quebram direto. Principalmente no primeiro acesso, quando ele irá fazer todo o processo de "virtualização" do browser pra gerar o cache da página. A solução que encontrei neste cenário foi a criação de bots pra ficarem acessando e atualizando o cache de minhas páginas.

Mas isto tudo já não é necessário graças ao Angular Universal

SEO Friendly

O universal irá servir o conteúdo da sua página da mesma maneira que uma aplicação totalmente server-side faz. Quando um bot visitar sua url, eles irão ver exatamente o que você vê clicando com o botão direito do mouse e visualizando o código fonte.

Social Media Friendly

Com o Angular Universal servindo seu conteúdo, basta você trabalhar bem suas meta tags. Você pode fazer isto utilizando a lib ngx-meta que é bem bacana e venho utilizado em todos meus projetos.

Pre-rendering

Quem disse que o Universal não tem pre-rendering? A questão é que aqui ele funciona de maneira integrada com angular, sem terceiros como phantom. Quando um usuário ou bot visita seu site, o servidor irá servir rapidamente uma versão pré-renderizada do conteúdo, ao invés de apenas servir os scripts e estilos para que o browser faça todo o trabalho.

Começando

E como faz pra começar? A equipe do angular universal fez dois starters interessantes e simples de se entender, me evitando escrever um longo post de configuração. Eu prefiro trabalhar com a versão do angular-cli por possuir menos boilerplate e ser de fácil entendimento, mas se preferir pode utilizar também como base a versão em webpack customizada.

Dependencias

Você vai precisar ter o último node e npm em seu ambiente + angular-cli

Clone Universal

$ git clone https://github.com/angular/universal-starter.git

Instale as dependencias

$ cd universal-starter/cli
$ npm install

Rode em modo de desenvolvimento

$ ng serve

Rode em modo dinâmico (SSR)

$ npm run build:dynamic && npm run serve:dynamic

Este é o modo em que será utilizado no seu projeto em produção. Note que devido a flag --prod passada internamento pelo comando ng build, o angular irá aplicar as variáveis de ambiente que estiverem em environments/environment.prod.ts.

Após a compilação, abra seu browser na porta indicada e veja o código fonte 💥

Boas práticas

Quando estamos trabalhando neste modelo, é sempre bom ter em mente que ocorrerão diversos tipos de problema, mas nada de outro mundo, que não possa ser resolvido. Vou citar abaixo algumas sacadas que percebi refatorando o site do meu produto Firetask.

Cuidado com o DOM

Sim. A razão disto é porque o Universal irá renderizar sua aplicação no servidor e lá não existe browser. Portanto tente evitar utilizar window, document ou jQuery.

Existem outras soluções mais seguras do angular para trabalhar com o DOM. Veja as API's ElementRef, Renderer e ViewContainer para mais detalhes.

Verificação de plataforma

Você tem a opção de contornar alguns problemas fazendo verificações de plataforma

import { Inject, Component, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

@Component({
    selector: 'app',
    template: `...`,
    styles: []
})
export class AppComponent {
    isBrowser: boolean;
    constructor(
        @Inject(PLATFORM_ID) public platformID: Object
    ) {
        this.isBrowser = isPlatformBrowser(this.platformID);
    }
    ngOnInit() {
        if (this.isBrowser) {
            window.alert('Whooa its a browser');
        }
    }
}

Desenvolva rodando os 2 ambientes

Quando estiver trabalhando, rode o ng serve em uma aba do terminal e em outra aba rode o comando de servir a aplicação de maneira dinâmica.

Pra facilitar o tamanho do comando, você pode criar um atalho no package.json

...
 "scripts": {
    "serve:universal": "npm run build:dynamic && npm run serve:dynamic"
  }
...

Evite o setTimeout

Atualmente existe uma issue aberta no universal sobre setTimeout() e setInterval(). Portanto tente evitá-los ao máximo. E na realidade, se parar pra pensar estas funções nem são de fato necessárias vindo do servidor. Se você realmente precisar disto no cliente, basta fazer a verificação de plataforma que citei mais acima.

Conclusão

Acredito que agora sim esta questão de SEO com Angular foi finalmente resolvida, apesar de ainda existirem alguns problemas, de qualquer forma já é possível colocar aplicações com renderização dinâmica em produção, sem medo.

Então é isso ai pessoal, esta foi a experiência que tive recentemente. Espero que tenham gostado, vou atualizando com o decorrer da jornada.

Happy coding

PS: Se interessou por este tipo de conteúdo? Meu treinamento Semana do Angular 2017 está rolando, dê uma conferida aqui.

Ebook Angular 4

Aprenda o novo angular praticando


Download PDF

Experiências "boas" e "ruins", estou compartilhando tudo em minha jornada com

Angular, Ionic e Firebase

Aprenda desenvolver melhor

Últimas do blog

Continue Lendo