Google Gaming: la puntuación perfecta para faros

Tras el lanzamiento de la actualización de Google Chrome Lighthouse, hice lo que haría cualquier empresario concienzudo: consulté mi sitio web. Para mi consternación, los resultados distaron mucho de ser satisfactorios... Los resultados fueron un golpe aplastante.

Jonathon Grantham

Siempre he dudado en compartir mi código. No es que crea que es malo, ni que tenga el síndrome del impostor. Lo que pasa es que compartir código me permite vislumbrar la locura que hay en mi mente, y eso es, de alguna manera, cruel para todos los demás. Permíteme guiarte en un viaje que casi me llevó al borde de la cordura. Todo comenzó con la actualización de Lighthouse de Google.

Para los usuarios no iniciados en SEO, la actualización de Lighthouse de Google supuso un cambio sustancial en la clasificación de las búsquedas, ya que dependía del rendimiento del sitio web y del cumplimiento de las mejores prácticas. Si quieres probar tu sitio web, solo tienes que abrirlo en Chrome en un ordenador de sobremesa, pulsar F12 para abrir las herramientas de desarrollo de Chrome y, a continuación, hacer clic en la pestaña «Lighthouse». Elige entre escritorio o móvil y haz clic en «Analizar». Después de aproximadamente un minuto, recibirás cinco puntuaciones, cada una de las cuales oscila entre 0 y 100, en cuanto al rendimiento, la accesibilidad, las mejores prácticas, el SEO y la aplicación web progresiva (PWA).

FrustranteAntes de profundizar en los detalles técnicos, permítanme presentarme. Mi nombre es Jonathan Grantham y soy el orgulloso propietario de una pequeña empresa de SaaS B2B, Nexoid, que se especializa en software ERP e ITSM. El sitio web del que hablo en este artículo es www.nexoid.com. No dudes en echar un vistazo, abre el código fuente. También puedes seguirme en LinkedIn. Mi perfil es www.linkedin.com/in/jonathongrantham/

Tras el lanzamiento de la actualización de Google Chrome Lighthouse, hice lo que haría cualquier empresario concienzudo: consulté mi sitio web. Para mi consternación, los resultados distaron mucho de ser satisfactorios. Con una puntuación de 21 sobre 100 en rendimiento, 0 en accesibilidad, 45 sobre 100 en mejores prácticas, 11 sobre 100 en SEO y un fracaso en la PWA, me sorprendió. Yo mismo había creado el sitio web, una arquitectura de una sola página bastante estándar, utilizando React.js. Los puntajes fueron un golpe aplastante.

Sin dejarme intimidar por el revés inicial, lancé MS Code y empecé a abordar los problemas uno por uno, siendo el rendimiento mi primer objetivo. Las guías incluidas en la herramienta Lighthouse resultaron muy útiles. Convertí todas las imágenes de archivos JPEG y PNG a archivos WebP modernos y me aseguré de que cada etiqueta img estuviera equipada con una propiedad de ancho y largo para evitar cambios de diseño. Estas modificaciones por sí solas aumentaron mi puntuación de 21/100 a 60/100. Fue una mejora significativa, pero está lejos de ser perfecta. La única sugerencia que quedaba era «reducir el JavaScript no utilizado», lo que no era particularmente útil. El único JavaScript presente era el framework React.js, ya que todo lo demás había sido eliminado.

Con Nexoid, AM Digital también pudo extender los beneficios de una solución ITSM unificada a sus operaciones orientadas al cliente. El portal de clientes, integrado con Azure, ofrecía una experiencia más conectada, dinámica y fluida para sus clientes, lo que se tradujo en un aumento de la satisfacción y el compromiso de los clientes. El portal permitía la sincronización en tiempo real con los datos de los clientes, lo que garantizaba que toda la información estuviera actualizada y fuera precisa, lo que mejoraba la prestación de sus servicios y fortalecía la relación cliente-empresa.

A pesar de mis esfuerzos persistentes por corregir el problema, me encontré con obstáculos constantes. Intenté eliminar partes de React.js, exploré la «carga diferida» y probé varios optimizadores y compresiones. Sin embargo, el problema provenía del propio React.js, que tenía un tamaño aproximado de medio megabyte.

Casi puedo escuchar a desarrolladores web experimentados gritar: «¡No uses React para un sitio web! ¡Está diseñado para crear aplicaciones web!» Ahora soy muy consciente de esto.

Lo que comenzó como una tarea aparentemente simple de convertir algunas imágenes ahora se ha transformado en una revisión completa del sitio web utilizando un nuevo marco. Frustrado y pronunciando unas cuantas palabras en voz baja, salí en busca de un sustituto adecuado. Primero consideré a Vue y más tarde a Angular, posiblemente los mayores competidores de React.js. Sin embargo, ambos presentaron el mismo problema.

En un intento por simplificar las cosas, decidí buscar tecnologías más antiguas y probé jQuery. Sin embargo, me encontré con el mismo problema. Quedó muy claro que no existía un marco de arquitectura de una sola página estándar que pudiera apaciguar a las deidades de Google.

Parecía que la única opción que me quedaba era recurrir a JavaScript básico.

Mi serie de experimentos comenzó con una página HTML básica sin JavaScript. Luego, probé una página HTML con un div cuyo contenido podía reemplazarse. Rápidamente me di cuenta de que hacer varios cambios simultáneos en la página a través de JavaScript generaba penalizaciones por parte de Lighthouse. La solución consistía en manipular el contenido de la etiqueta principal como una cadena y, a continuación, reintegrarla, con lo que se creaba un único cambio visible en el DOM.

Ahora tenía una página HTML minimalista con una etiqueta de cuerpo vacía, complementada con una pequeña función de descarga en la etiqueta principal. Esta función inspeccionó la URL y ejecutó una solicitud HTML GET para recuperar el archivo de texto correspondiente que contenía el HTML principal de la página. Se podría pensar que esta es una solución adecuada. Desafortunadamente, no fue suficiente cuando intenté cargar dinámicamente la funcionalidad de JavaScript.

A diferencia de otras etiquetas, si agregas una etiqueta de script con una alerta simple («sí, esto se disparó») en la cadena de contenido del cuerpo, no se ejecutará. Aunque no era lo ideal, una solución alternativa consistía en analizar el cuerpo de la cadena, identificar todo el contenido de las etiquetas del script y colocarlo en una función de evaluación de JavaScript. El enfoque era un tanto eficaz, pero tropezaba con los espacios de nombres y la consola de desarrolladores estaba repleta de advertencias antiestéticas. La solución consistía en extraer las etiquetas del script del HTML y añadirlas como elemento de script una vez renderizado el DOM. Google no penalizó esta acción por alguna razón.

Se estaban haciendo progresos y disponía de una solución básica de arquitectura de una sola página. Pero no tan rápido. Si bien Google es eficiente a la hora de indexar páginas con arquitectura de una sola página (lo hace abriéndolas en un navegador, dejando que se ejecute todo el código JavaScript y, a continuación, escaneando el DOM), Bing, Yahoo y otros motores de búsqueda importantes utilizan un método similar y más sencillo. Sin embargo, la mayoría de las demás plataformas, como Facebook, Reddit, LinkedIn y WhatsApp, solo obtienen el archivo HTML, recuperando un pequeño archivo HTML con el cuerpo en blanco. Mi solución no era viable. Ahora tenía que replicar este concepto para cada página del sitio web e incluir el JavaScript para cambiar al modo de arquitectura de una sola página cuando un usuario hacía clic en un enlace.

Necesitaba una herramienta capaz de generar HTML para cada página, basada en mi solución. Se me ocurrió que tenía el recurso perfecto a mi disposición: mi propio sistema ERP, Nexoid. Creé un modelo de Nexoid que abarca un sitio web y objetos de datos de una página web. El registro del sitio web facilitó la creación de una plantilla genérica de página web, mientras que los registros de la página web contenían el contenido de cada página individual. La última pieza del rompecabezas era una función de flujo de trabajo o un script que pudiera leer el registro del sitio web y todos los registros de la página web relacionados para generar los archivos HTML. Después de unos días, estaba en funcionamiento. Había creado un sistema de gestión de contenidos (CMS) básico. Desarrollar un CMS hasta este punto no es demasiado complejo; el verdadero desafío surge cuando se integran otros flujos de trabajo, aprobaciones, localizaciones, vistas previas, etc. del CMS.

Un requisito clave para el nuevo sitio web era la localización; nuestro objetivo era lanzarlo en 11 idiomas. Al ser una empresa de TI, me incliné naturalmente por las soluciones tecnológicas. En lugar de contratar a un traductor para cada página, opté por AWS Translate. Si bien los traductores de IA son decentes, no son perfectos y los errores son lo suficientemente notables como para revelar un origen no humano. Un miembro del personal francófono evaluó la traducción de la IA y le dio un 6/10, describiéndola como «entendible, pero no del francés correcto».

Sin embargo, nos topamos con un truco valioso. Descubrimos que, al introducir primero el texto en inglés en ChatGPT, pedirle que «lo ordene» y, después, pegarlo, se reformula el texto de una forma que sigue siendo inglesa, pero que es mucho más compatible con los modelos lingüísticos. Usar el inglés reformulado por ChatGPT como base para la traducción mejora significativamente la calidad de la traducción, elevándola a un 9 o incluso a un 10 perfecto sobre 10.

Después de haber desarrollado una base tecnológica sólida para crear el sitio web, estaba progresando. Sin embargo, surgió un nuevo desafío cuando empezamos a crear páginas más complejas. Según las nuevas directrices de Lighthouse, se hizo necesario consolidar todo el código JavaScript, CSS y HTML en un solo archivo. Esto también se aplicaba a las versiones de arquitectura de una sola página.

Recurrimos a insertar todos los archivos JavaScript y CSS como etiquetas en línea. Se requería una estrategia similar para la versión de arquitectura de una sola página. Creamos un archivo JSON que contiene todos los scripts, estilos y HTML.

Lighthouse identificó el siguiente problema como el tamaño de los activos; los archivos de página HTML y JSON eran demasiado grandes. Resolví este problema con «minify», una biblioteca de Node.js diseñada específicamente para comprimir archivos HTML, CSS y JavaScript. Esta solución permitió reducir el tamaño de los archivos de texto en más de un 40%. Además, minify ofrecía el beneficio adicional de la ofuscación, lo que dificultaba la lectura del código sin procesar y mejoraba la seguridad.

Profundicemos en el tema del hospedaje. Tradicionalmente, un sistema de gestión de contenidos (CMS) funciona a través de un servidor de aplicaciones que gestiona la solicitud HTML del usuario. Interpreta la solicitud de página desde la URL, localiza los activos correspondientes en una base de datos, recupera el registro de la base de datos (posiblemente junto con otros), procesa la información para armar la página y, finalmente, la entrega al usuario final como un documento HTML plano. Esta descripción se refiere principalmente a la solicitud HTML inicial cuando un usuario visita un sitio web nuevo, aunque conozco AJAX y otras tecnologías similares.

Sin embargo, este modelo convencional presenta ciertos inconvenientes en el contexto del nuevo mundo de los faros. En primer lugar, la comunicación de ida y vuelta entre el servidor de aplicaciones y el servidor de la base de datos, así como la compilación de las páginas, provocan retrasos. En segundo lugar, en su forma más sencilla, un servidor de aplicaciones y un servidor de bases de datos solo están disponibles físicamente en una única ubicación. Esta configuración es excelente si se encuentra en el mismo edificio o ciudad, pero es significativamente menos eficiente si intenta acceder al sitio desde el otro lado del mundo. Por ejemplo, la latencia media del ping entre Australia y el Reino Unido es de aproximadamente 250 milisegundos.

Nuestra solución a estos desafíos implica utilizar AWS S3 para alojar los archivos estáticos generados por el script de publicación mencionado anteriormente y AWS CloudFront para la distribución global de contenido. En el momento de escribir este artículo, AWS CloudFront distribuía contenido a más de 90 ciudades de 47 países. Para una persona de Melbourne (Australia) que accedía a un sitio web del Reino Unido, AWS CloudFront redujo la latencia del ping de 250 milisegundos a tan solo 13 milisegundos (esta es la diferencia horaria entre los servidores perimetrales de Melbourne y los de AWS en Sídney).

Llegamos ahora al componente de aplicación web progresiva (PWA) de la prueba Lighthouse, que no era algo a lo que hubiera prestado mucha atención anteriormente. Para aquellos que no estén familiarizados, una PWA involucra a un trabajador de un servicio de JavaScript que administra el sitio web como una aplicación web. Si eso es un poco complejo, considérelo de esta manera: se trata esencialmente de una herramienta automática de descarga y almacenamiento en caché. Cuando un usuario visita tu sitio web, el objetivo es hacer que sus solicitudes posteriores sean lo más rápidas y fluidas posible. El service worker de la PWA te permite tener ya descargados los siguientes activos en la máquina local del usuario, lo que elimina la necesidad de realizar otra solicitud GET de Internet.

En el momento de escribir este artículo, el sitio web de Nexoid es relativamente pequeño y contiene solo 19 páginas. Sin embargo, esas 19 páginas están traducidas a 11 idiomas diferentes, lo que hace un total de 209 páginas. Al principio, traté de descargar todos los recursos al service worker, que sumaban alrededor de 5 MB. Este tamaño era demasiado grande para una carga inicial y Lighthouse me penalizó por ello. Decidí descargar solo los archivos JSON de la página en inglés, que incluyen todos los archivos CSS, HTML y JavaScript necesarios para mostrar cada página.

La estructura final es la siguiente: un depósito de S3 aloja los archivos HTML compilados, nombrados sin la extensión.html. Por ejemplo, www.nexoid.com/en representa el HTML de la página de inicio en inglés, www.nexoid.com/de representa el HTML de la página de inicio en alemán y www.nexoid.com/en/platform hace referencia al HTML de la plataforma en inglés, y así sucesivamente. Además, hay archivos JSON que contienen las partes del cuerpo y la cabeza que cambian al navegar entre páginas, como https://www.nexoid.com/en.json, https://www.nexoid.com/de.json y https://www.nexoid.com/en/platform.json, entre otros.

En conclusión, comprender Lighthouse planteó un desafío importante. Soy escéptico de que los productos CMS tradicionales y listos para usar puedan abordar esta tarea de manera eficaz. Reflexionando sobre mi experiencia con plataformas como WordPress y Drupal, me cuesta creer que puedan optimizarse para lograr una puntuación perfecta en Lighthouse. En general, creo que el esfuerzo merece la pena, y Google tiene razón para poner más énfasis en el rendimiento. Sin embargo, este cambio es y seguirá siendo un problema considerable para los diseñadores web y las agencias.

Si está interesado en obtener más información sobre Lighthouse o si desea hablar sobre los productos y servicios de Nexoid, no dude en ponerse en contacto con nosotros. Puedes ponerte en contacto con nosotros a través de LinkedIn o a través de la página «Contacta con nosotros» de nuestro sitio web.