Procesamiento dinámico con Rendertron

Jueves, 31 de enero de 2019

Muchos frameworks de frontend dependen de JavaScript para mostrar contenido. Esto puede hacer que Google tarde un tiempo en indexar tu contenido o actualizarlo.

Una solución alternativa que analizamos en Google I/O este año es el procesamiento dinámico. Hay muchas maneras de implementarlo. En esta entrada de blog, se muestra un ejemplo de implementación de procesamiento dinámico con Rendertron, una solución de código abierto basada en Chromium sin interfaz gráfica.

¿Qué sitios deberían considerar la renderización dinámica?

No todos los motores de búsqueda o bots de redes sociales que visitan tu sitio web pueden ejecutar JavaScript. Googlebot podría tardar en ejecutar JavaScript y tiene algunas limitaciones, por ejemplo.

El procesamiento dinámico es útil para el contenido que cambia con frecuencia y necesita JavaScript para mostrarse. La experiencia del usuario con tu sitio (en especial, el tiempo hasta la primera pintura significativa) puede beneficiarse con respecto al procesamiento híbrido (por ejemplo,Angular Universal).

¿Cómo funciona la renderización dinámica?

Cómo funciona la renderización dinámica

La renderización dinámica implica alternar entre contenido procesado por el cliente y contenido procesado previamente para usuarios-agentes específicos.

Necesitarás un procesador para ejecutar JavaScript y producir código HTML estático. Rendertron es un proyecto de código abierto que usa Chromium sin interfaz gráfica para la renderización. Las apps de una sola página suelen cargar datos en segundo plano o postergar el trabajo para renderizar su contenido. Rendertron cuenta con mecanismos para determinar el momento en que se completa la renderización de un sitio web. Espera hasta que todas las solicitudes de red finalicen y no haya trabajo pendiente.

Esta publicación abarca lo siguiente:

  1. Consulta una aplicación web de muestra
  2. Configura un servidor express.js pequeño para publicar la aplicación web.
  3. Instala y configura Rendertron como middleware para procesamiento dinámico

La aplicación web de muestra

La aplicación web Kitten Corner usa JavaScript para cargar una variedad de imágenes de gatos desde una API y las muestra en una cuadrícula.

Imágenes tiernas de gatos en una cuadrícula y un botón para mostrar más: esta aplicación web realmente lo tiene todo.

Este es el 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);

La aplicación web usa JavaScript moderno (ES6), que aún no se admite en Googlebot. Podemos usar la prueba de optimización para dispositivos móviles a fin de comprobar si Googlebot puede ver el contenido:

La prueba de optimización para dispositivos móviles muestra que la página está optimizada para dispositivos móviles, pero faltan capturas de pantalla de todos los gatos. Aparecen el titular y el botón, pero ninguna de las imágenes de gatos está allí.

Si bien este problema es simple de corregir, te recomendamos que aprendas a configurar la renderización dinámica. La renderización dinámica permitirá que Googlebot vea las fotos de los gatos sin cambiar el código de la aplicación web.

Configura el servidor

Para publicar la aplicación web, usaremos express, una biblioteca node.js, para compilar servidores web.

El código del servidor se ve de la siguiente forma (busca el código fuente completo del proyecto aquí):

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}`);
});

Puedes probar el ejemplo en tiempo real. Si usas un navegador actualizado, deberías ver varias imágenes de gatos. Si quieres ejecutar el proyecto desde tu computadora, necesitas node.js para ejecutar los siguientes comandos:

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

Luego, dirige tu navegador a https://localhost:8080. Ahora es momento de configurar la renderización dinámica.

Implementa una instancia de Rendertron

Rendertron ejecuta un servidor que toma una URL y muestra código HTML estático para la URL con Chromium sin interfaz gráfica. Seguiremos la recomendación del proyecto Rendertron y usaremos Google Cloud Platform.

El formulario para crear un proyecto nuevo de Google Cloud Platform.

Ten en cuenta que puedes comenzar con el nivel de uso que está disponible sin cargo. El uso de esta configuración para la producción puede generar costos según los precios de Google Cloud Platform..

  1. Crea un proyecto nuevo en Google Cloud Console. Anota el “ID del proyecto” debajo del campo de entrada.
  2. Instala el SDK de Google Cloud como se describe en la documentación y accede a tu cuenta.
  3. Para clonar el repositorio de Rendertron desde GitHub, usa lo siguiente:
    git clone https://github.com/GoogleChrome/rendertron.git
    cd rendertron
  4. Para instalar dependencias y compilar Rendertron en tu computadora, ejecuta los siguientes comandos:
    npm install && npm run build
  5. Habilita la caché de Rendertron mediante la creación de un archivo nuevo llamado config.json in the en el directorio de Rendertron con el siguiente contenido:
    { "datastoreCache": true }
  6. Ejecuta el siguiente comando desde el directorio rendertron. Sustituye YOUR_PROJECT_ID por el ID de tu proyecto del paso 1.
    gcloud app deploy app.yaml --project YOUR_PROJECT_ID
  7. Selecciona la región que quieras y confirma la implementación. Espera a que termine.
  8. Ingresa la URL YOUR_PROJECT_ID.appspot.com. Deberías ver la interfaz de Rendertron con un campo de entrada y algunos botones.
IU de Rendertron después de la implementación en Google Cloud Platform

Cuando veas la interfaz web de Rendertron, significa que implementaste correctamente tu propia instancia de Rendertron. Toma nota de la URL del proyecto (YOUR_PROJECT_ID.appspot.com), ya que la necesitarás en la próxima parte del proceso.

Agrega Rendertron al servidor

El servidor web usa express.js, y Rendertron tiene un middleware express.js. Ejecuta el siguiente comando en el directorio del archivo server.js:

npm install --save rendertron-middleware

Con este comando, se instala el middleware de rendertron desde la administración de socios de red para que podamos agregarlo al servidor:

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

Configura la lista de bots

Rendertron usa el encabezado HTTP user-agent para determinar si una solicitud proviene de un bot o del navegador de un usuario. Tiene una lista bien mantenida de usuarios-agentes de bot para comparar. De forma predeterminada, esta lista no incluye Googlebot, ya que Googlebot puede ejecutar JavaScript. Para hacer que Rendertron también procese las solicitudes de Googlebot, agrega Googlebot a la lista de usuarios-agentes:

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

Rendertron compara el encabezado user-agent con esta expresión regular más adelante.

Agrega el middleware

Para enviar solicitudes de bots a la instancia de Rendertron, debemos agregar el middleware a nuestro servidor express.js. El middleware verifica el usuario-agente solicitante y reenvía las solicitudes de bots conocidos a la instancia de Rendertron. Agrega el siguiente código a server.js y no olvides sustituir YOUR_PROJECT_ID por el ID de tu proyecto de Google Cloud Platform:

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

Los bots que solicitan el sitio web de muestra reciben el código HTML estático de Rendertron, por lo que los bots no necesitan ejecutar JavaScript para mostrar el contenido.

Prueba nuestra configuración

Para probar si se realizó correctamente la configuración de Rendertron, vuelve a ejecutar la prueba de optimización para dispositivos móviles.

La prueba de optimización para dispositivos móviles muestra que la página está optimizada para dispositivos móviles y ahora la captura de pantalla contiene todos los gatos faltantes.

A diferencia de la primera prueba, las fotos de los gatos están visibles. En la pestaña HTML, podemos ver todo el código HTML que generó JavaScript y que Rendertron eliminó la necesidad de que JavaScript muestre el contenido.

Conclusión

Creaste una configuración de renderización dinámica sin hacer ningún cambio en la aplicación web. Con estos cambios, puedes publicar una versión HTML estática de la aplicación web para los rastreadores.