Optimizando Ruby on Rails para Google Web Vitals parte 1

Mixer Gutiérrez
Building La Haus
Published in
7 min readApr 16, 2021

Este es el primer post, de una serie de tres, sobre cómo hemos optimizado nuestras páginas principales para nuestros usuarios y Google, mientras le sacamos el máximo provecho al stack que tenemos. En esta ocasión, hablaremos sobre cómo optimizamos nuestro Home.

Los Web Vitals son indicadores de calidad que Google considera esenciales para entregar una gran experiencia de usuario en la web, y desde mayo de 2021 serán tenidos en cuenta en el ranking de búsqueda.

LCP, FID y CLS. Los Web Vitals iniciales que Google tendrá en cuenta en el ranking de resultados de búsqueda.

Si estás usando Rails como un monolito, no tienes que reescribir todo tu Front-End para obtener más de 80 puntos en rendimiento en los Web Vitals de Google. Sigue leyendo para conocer la estrategia que usamos para lograrlo.

Contexto

Cuando participamos en un Google Launchpad en Mexico en 2019 nos llevamos una gran decepción. Nuestra página principal, que tiene pocos elementos interactivos y un contenido en su mayoría estático, tuvo una calificación de 40 puntos sobre 100 en una herramienta llamada PageSpeed Insights lo cual es pésimo.

Para aquellos que no conocen PageSpeed Insights o Web Vitals, acá va una breve descripción:

  • PageSpeed Insights: Herramienta que analiza el contenido de una página web y provee sugerencias para mejorar su velocidad.
  • Web Vitals: Indicadores de calidad que Google considera esenciales para entregar una gran experiencia de usuario en la web.

Tener un sitio veloz es crítico, pues hay estudios que correlacionan la demora en el tiempo de carga de una página con pérdida de visitantes, bajo “engagement”, frustración por parte de los usuarios, entre otros.

Teniendo en cuenta la baja velocidad en las conexiones celulares y las bajas especificaciones de los dispositivos móviles en Latinoamérica, reforzamos la importancia de trabajar en este frente.

De vuelta en Colombia, decididos a darle vuelta a la situación, investigamos las razones por tan bajo rendimiento y encontramos dos problemas:

  • Todo el contenido HTML estaba inmerso en nuestros componentes de Vue.js, lo que aumentó el tamaño del Javascript e hizo necesario usar herramientas como Prerender.io para pre-procesar nuestro contenido para Google.
  • Nuestro CSS era enorme. Al usar librerías como Bootstrap, debíamos cargarlo al principio de la página para evitar que se viera terrible en la primera carga.
Esto es lo que vería un usuario por varios segundos mientras carga el CSS ubicado al final del <body>

Luego de lanzar ideas con el equipo, llegamos a las siguientes opciones:

Opción 1: Reescribir todo nuestro Front-End en un framework como Nuxt y usar el Server Side Rendering para solucionar el problema de velocidad e indexación.

Desventajas:

  • No teníamos el ancho de banda en el equipo.
  • No sabíamos cuánto tiempo nos podía tomar reescribirlo todo y cómo afectaría aspectos como manejo de sesiones y rutas de la aplicación.
  • Debíamos parar todos los nuevos features hasta que el nuevo código estuviera al día.

Opción 2: Reescribir nuestros componentes de Front-End en una librería como React on Rails que tiene en sus componentes la opción de Server Side Rendering.

Desventajas:

  • El equipo debía aprender y migrar todo a React.
  • El peso de la librería de React en su momento era alto y se debía asumir dicho costo en la carga de la página incluso si el componente era algo sencillo.

Opción 3: Intentar hacer una librería como React on Rails pero usando Vue.js

Desventajas:

  • No teníamos idea de cómo hacerlo ni sabíamos cuánto nos podía tardar.

Opción 4: Servir el HTML desde Rails y usar Javascript puro para reconstruir las interacciones.

Desventajas:

  • Perder la comodidad y posibilidad de reutilizar plugins y funcionalidades de Vue.js
  • Debíamos contar con desarrolladores experimentados en Javascript para las interacciones más complejas.

¿Qué hicimos?

Luego de hacer pruebas de concepto para cada una de las opciones que teníamos, decidimos arriesgarnos por la opción en la que se usaba el renderizado de HTML desde Rails y se combinaba con un código liviano para el CSS y Javascript.

  1. HTML

Una de las ventajas de Ruby on Rails es que tiene la facultad de devolver el HTML listo para Google. Este HTML es indexable y el código puede optimizarse fácilmente para que la respuesta sea lo más rápida posible.

Con esto conseguimos dejar de usar Prerender.io y ganamos el control exacto de lo que queríamos Google indexara o no.

2. CSS

Implementar un CSS eficiente tenía su parte retadora:

  • Si se agrega al final de la etiqueta <body>el sitio se verá sin estilos hasta que el navegador llegue a esa parte, lo descargue y procese.
  • Si se agrega dentro de la etiqueta <head> pero es pesado, se convertirá en un recurso bloqueante al momento de la primera carga de la página y el usuario verá una página en blanco hasta que el navegador termine de descargarlo y procesarlo.

Ambas cosas pueden percibirse durante un par de segundos en una red lenta.

Solución:

  • Usar un framework CSS como TailwindCSS (mucho más liviano que Bootstrap)
  • Inyectar los estilos CSS en nuestro HTML para evitar cargar un recurso externo
Helpers que extraen el CSS generado por Webpack y retornan HTML seguro para ser inyectado directamente dentro de la etiqueta <head>

Usando ambas estrategias obtuvimos un código liviano y que no bloqueaba la renderización de la página en la carga inicial.

3. Javascript

Una vez solucionados los retos del contenido (HTML) y del aspecto visual (CSS) quedaban pendientes los retos de la parte interactiva (Javascript), que no distaban mucho de los anteriores:

  • El código Javascript, dada su complejidad, puede tardar más tiempo en ser procesado que el código CSS, por lo que se debe limitar mucho su uso en la carga inicial.
  • El framework que se use, la cantidad de librerías y la forma como se importan impactan significativamente el peso final del archivo Javascript que se incluye en la página.

Solución:

  • Usar un primer archivo ultraliviano escrito en Javascript puro para la primera carga: lo básico como para ocultar tabs, menús, etc.
  • Usar un segundo archivo de Javascript, activando su descarga y ejecución luego de que el usuario haga alguna interacción (Ej: Scroll, Clic, etc)

Acá, el lazy_promise_runner.js contiene el código que escucha las interacciones de usuario sobre las cuales nos interesa activar la descarga y ejecución del código que no es necesario para la carga inicial.

Y home_extra.js es el archivo de Javascript que contiene el código especifico de esas interacciones no necesarias para la carga inicial pero que son vitales para una correcta experiencia de usuario, tales como: sliders, modales, etc.

De esta forma, logramos implementar de manera muy básica un patrón PRPL (https://web.dev/apply-instant-loading-with-prpl).

Nuestros Resultados:

Nuestro Home (página principal) se ha mantenido de forma consistente entre 85 y 95 desde la implementación, a pesar de que se le hacen cambios cada mes.

Nuestros Aprendizajes

  1. Verificar la indexación

Si lo que se está buscando es ganar posicionamiento en Google, es de vital importancia asegurarse de que el contenido es indexable y visible para Google. Durante mucho tiempo estuvimos convencidos de que Google “veía” el contenido dentro de nuestros componentes de Vue.js y para sorpresa nuestra, no era así (a pesar de que en alguna documentación se afirmaba que los crawlers esperaban la carga de Javascript y también analizaban ese contenido).

Esto se puede hacer usando herramientas como el URL Inspect Tool de Google Search Console o incluso usando un curl y verificando que no existan “placeholders” de Javascript como {{ nombreVariable }}.

Si luego de revisar, se tiene este problema, activar el Server-Side-Rendering (SSR) del framework que estén usando puede resolverlo o también se puede usar una solución de forma temporal como Prerender.io

2. Aprender a usar herramientas de medición de velocidad

Los Web Vitals y métricas relacionadas a velocidad del sitio se pueden medir fácilmente y no son una caja negra. Algunas de estas herramientas son:

Hay varios conceptos que aprender que pueden llegar a ser un poco densos pero definitivamente vale la pena desarrollar dicha habilidad, cada incremento en velocidad se paga solo.

Además, como nos ha dicho Andy Young, uno de los Partners en Kaszek:

“Performance is a matter of pride” — Andy Young

3. Tomar el tiempo para realizar pruebas de concepto

Siendo ingenieros, es natural el sentimiento de querer saltar a solucionar el problema que se nos presente con la herramienta que mejor manejamos, la que queremos probar o la que vimos que en otra parte funcionaba. Sin embargo, muchas veces ignoramos el impacto que esto puede traer al negocio y hasta ignoramos qué métricas debemos tener en cuenta para garantizar el éxito de la decisión que tomamos.

Por esto, siempre recordamos lo importante que fue en su momento validar las opciones que teníamos con pruebas de concepto. No tomaron más allá de una mañana para 3 desarrolladores y nos dieron la tranquilidad de que íbamos por el mejor camino, dadas las restricciones que teníamos.

En las próximas entregas de esta serie, contaremos cómo fue el proceso para optimizar nuestras páginas de propiedades y nuestras páginas de búsqueda.

Recomendados

En La Haus y LaHaus.mx seguimos trabajando incansablemente para ser los mejores en producto y tecnología en Colombia y Latinoamérica. Cualquier contribución a este post es recibida con mucha gratitud, me puedes escribir a mixergutierrez@lahaus.com. Si quieres aplicar a La Haus este es link para hacerlo

--

--