Renderização dinâmica com o Rendertron

Quinta-feira, 31 de janeiro de 2019

Muitas estruturas de front-end usam JavaScript para exibir conteúdo. Por isso, talvez o Google demore um pouco para indexar seu conteúdo ou atualizar o material indexado.

Uma alternativa que discutimos no Google I/O deste ano foi a renderização dinâmica. Há muitas maneiras de implementar esse recurso. Esta postagem do blog mostra um exemplo de implementação da renderização dinâmica usando o Rendertron, uma solução de código aberto baseada no Chromium headless.

A renderização dinâmica pode ser útil para quais sites?

Nem todos os mecanismos de pesquisa ou bots de mídia social que acessam seu site são compatíveis com JavaScript. O Googlebot, por exemplo, pode demorar para processar JavaScript e tem algumas limitações.

A renderização dinâmica é útil para conteúdo que é alterado com frequência e precisa de JavaScript para ser exibido. A experiência do usuário no seu site (principalmente o tempo até a primeira exibição significativa) pode melhorar com o uso da renderização híbrida. Por exemplo, com a Angular Universal.

Como funciona a renderização dinâmica?

Como funciona a renderização dinâmica

Renderização dinâmica significa alternar entre conteúdo renderizado no lado do cliente e conteúdo pré-renderizado para user agents específicos.

É preciso usar um renderizador para executar o JavaScript e gerar HTML estático. O Rendertron é um projeto de código aberto que usa o Chromium headless para renderização. Muitas vezes, os apps de página única carregam dados em segundo plano ou adiam tarefas para renderizar o conteúdo. O Rendertron tem mecanismos para determinar quando a renderização do site foi concluída. Ele aguarda até que todas as solicitações de rede tenham terminado e não haja processos pendentes.

Esta postagem abrange o seguinte:

  1. App da Web de amostra
  2. Como configurar um pequeno servidor express.js para disponibilizar o app da Web
  3. Como instalar e configurar o Rendertron como um middleware para renderização dinâmica

App da Web de amostra

O app da Web "kitten corner" usa JavaScript para carregar e exibir várias imagens de gatos de uma API em uma grade.

O app tem tudo o que você precisa: imagens de gatinhos dispostas em grade e um botão para mostrar mais.

Veja o código JavaScript:

const apiUrl = 'https://api.thecatapi.com/v1/images/search?limit=50';
   const tpl = document.querySelector('template').content;
   const container = document.querySelector('ul');
   function init () {
     fetch(apiUrl)
     .then(response => response.json())
     .then(cats => {
       container.innerHTML = '';
       cats
         .map(cat => { const li = document.importNode(tpl, true); li.querySelector('img').src = cat.url; return li;
         }).forEach(li => container.appendChild(li));
     })
   }
   init();
   document.querySelector('button').addEventListener('click', init);

O app da Web usa JavaScript moderno (ES6), que ainda não é compatível com o Googlebot. Use o teste de compatibilidade com dispositivos móveis para verificar se o Googlebot consegue acessar o conteúdo:

O teste indica que a página é compatível com dispositivos móveis, mas a captura de tela
          não mostra os gatos. O título e o botão aparecem, mas as fotos dos gatos
          não.

Esse problema é fácil de corrigir, mas é ótimo para aprender como configurar a renderização dinâmica. Com ela, o Googlebot consegue encontrar as fotos dos gatos sem necessidade de mudanças no código do app.

Configurar o servidor

Para exibir o app da Web, vamos usar a express, uma biblioteca node.js, para criar servidores da Web.

Veja a seguir o código do servidor. Consulte também o código-fonte completo do projeto:

const express = require('express');
const app = express();
const DIST_FOLDER = process.cwd() + '/docs';
const PORT = process.env.PORT || 8080;
// Serve static assets (images, css, etc.)
app.get('*.*', express.static(DIST_FOLDER));
// Point all other URLs to index.html for our single page app
app.get('*', (req, res) => {
  res.sendFile(DIST_FOLDER + '/index.html');
});
// Start Express Server
app.listen(PORT, () => {
  console.log(`Node Express server listening on https://localhost:${PORT} from ${DIST_FOLDER}`);
});

Veja o exemplo publicado. Se você usar um navegador moderno, serão exibidas várias fotos de gatos. Para executar o projeto no computador, é necessário ter o node.js para executar os seguintes comandos:

npm install --save express rendertron-middleware
node server.js

Em seguida, direcione o navegador para https://localhost:8080. Agora é hora de configurar a renderização dinâmica.

Implantar uma instância do Rendertron

O Rendertron usa um servidor que recebe um URL e retorna o HTML estático desse URL usando o Chromium headless. Vamos seguir a recomendação do projeto Rendertron e usar o Google Cloud Platform.

Esse é o formulário para criar um novo projeto do Google Cloud Platform.

Você pode começar com o nível de uso disponível sem custo financeiro. O uso dessa configuração na produção pode ter custos, cobrados de acordo com os preços do Google Cloud Platform.

  1. Crie um novo projeto no Console do Google Cloud. Anote o "ID do projeto" abaixo do campo de entrada.
  2. Instale o SDK Google Cloud conforme descrito na documentação e faça login.
  3. Clone o repositório do Rendertron no GitHub com o comando:
    git clone https://github.com/GoogleChrome/rendertron.git
    cd rendertron
  4. Use os seguintes comandos para instalar as dependências e criar o Rendertron no seu computador:
    npm install && npm run build
  5. Para ativar o cache do Rendertron, crie um novo arquivo chamado config.json no diretório "rendertron" com o seguinte conteúdo:
    { "datastoreCache": true }
  6. Use o comando a seguir no diretório rendertron. Substitua YOUR_PROJECT_ID pelo ID do projeto da etapa 1.
    gcloud app deploy app.yaml --project YOUR_PROJECT_ID
  7. Selecione uma região e confirme a implantação. Aguarde a conclusão do processo.
  8. Digite o URL YOUR_PROJECT_ID.appspot.com. Você verá a interface do Rendertron com um campo de entrada e alguns botões.
IU do Rendertron após a implantação no Google Cloud Platform

Quando a interface da Web do Rendertron é exibida, isso indica que a instância do Rendertron foi implantada corretamente. Anote o URL do projeto (YOUR_PROJECT_ID.appspot.com), porque você vai precisar dele na próxima parte do processo.

Adicionar o Rendertron ao servidor

O servidor da Web está usando express.js, e o Rendertron tem um middleware express.js. Use o seguinte comando no diretório do arquivo server.js:

npm install --save rendertron-middleware

Esse comando instala o rendertron-middleware do npm para que ele possa ser adicionado ao servidor:

const express = require('express');
const app = express();
const rendertron = require('rendertron-middleware');

Configurar a lista de bots

O Rendertron usa o cabeçalho HTTP user-agent para determinar se uma solicitação vem de um bot ou do navegador de um usuário. Ele tem uma lista atualizada de user agents de bots para comparação. Por padrão, essa lista não inclui o Googlebot, porque ele é compatível com JavaScript. Adicione o Rendertron à lista de user agents para que ele também renderize solicitações do Googlebot:

const BOTS = rendertron.botUserAgents.concat('googlebot');
const BOT_UA_PATTERN = new RegExp(BOTS.join('|'), 'i');

Depois o Rendertron compara o cabeçalho user-agent com essa expressão regular.

Adicionar o middleware

Para enviar solicitações de bot à instância do Rendertron, é preciso adicionar o middleware ao servidor express.js. O middleware verifica o user agent solicitante e encaminha solicitações de bots conhecidos à instância do Rendertron. Adicione o seguinte código ao server.js e não se esqueça de substituir YOUR_PROJECT_ID pelo ID do projeto do Google Cloud Platform:

app.use(rendertron.makeMiddleware({
  proxyUrl: 'https://YOUR_PROJECT_ID.appspot.com/render',
  userAgentPattern: BOT_UA_PATTERN
}));

Os bots que solicitam o site de amostra recebem o HTML estático do Rendertron. Assim eles não precisam de JavaScript para exibir o conteúdo.

Testar a configuração

Para ver se está tudo certo com a configuração do Rendertron, faça o teste de compatibilidade com dispositivos móveis novamente.

Esse teste indica que a página é compatível com dispositivos móveis, e a captura de tela agora mostra
          todos os gatos.

Ao contrário do primeiro teste, agora as imagens de gatos estão visíveis. Na guia "HTML", é possível ver todo o HTML gerado pelo código JavaScript e confirmar que o Rendertron dispensou a necessidade de JavaScript para exibir o conteúdo.

Conclusão

Você criou uma configuração de renderização dinâmica sem mudar o app da Web. Com essas mudanças, é possível exibir uma versão HTML estática do app da Web para rastreadores.