Cómo mejoramos nuestro Core Web Vitals (estudio de caso)
Publicado: 2022-03-10El año pasado, Google comenzó a enfatizar la importancia de Core Web Vitals y cómo reflejan la experiencia real de una persona cuando visita sitios en la web. El rendimiento es una característica central de nuestra empresa, Instant Domain Search, está en el nombre. Imagine nuestra sorpresa cuando descubrimos que nuestros puntajes vitales no eran buenos para muchas personas. Nuestras computadoras rápidas e Internet de fibra enmascararon la experiencia que las personas reales tienen en nuestro sitio. No pasó mucho tiempo antes de que un mar de avisos rojos "pobres" y amarillos "necesita mejorar" en nuestra consola de búsqueda de Google requiriera nuestra atención. La entropía había ganado y teníamos que descubrir cómo eliminar el bloqueo y hacer que nuestro sitio fuera más rápido.
Fundé Instant Domain Search en 2005 y lo mantuve como actividad secundaria mientras trabajaba en una empresa de Y Combinator (Snipshot, W06), antes de trabajar como ingeniero de software en Facebook. Recientemente hemos crecido hasta convertirnos en un pequeño grupo con sede principalmente en Victoria, Canadá, y estamos trabajando en una larga acumulación de nuevas funciones y mejoras de rendimiento. Nuestros bajos puntajes de signos vitales web y la inminente actualización de Google hicieron que nos concentráramos en encontrar y solucionar estos problemas.
Cuando se lanzó la primera versión del sitio, lo construí con PHP, MySQL y XMLHttpRequest. Internet Explorer 6 era totalmente compatible, Firefox estaba ganando participación y Chrome aún estaba a años de su lanzamiento. Con el tiempo, hemos evolucionado a través de una variedad de generadores de sitios estáticos, marcos JavaScript y tecnologías de servidor. Nuestra pila de front-end actual es React servido con Next.js y un servicio de back-end integrado Rust para responder a nuestras búsquedas de nombres de dominio. Tratamos de seguir las mejores prácticas brindando todo lo que podemos a través de un CDN, evitando tantos scripts de terceros como sea posible y usando gráficos SVG simples en lugar de PNG de mapa de bits. No fue suficiente.
Next.js nos permite construir nuestras páginas y componentes en React y TypeScript. Cuando se combina con VS Code, la experiencia de desarrollo es increíble. Next.js generalmente funciona transformando los componentes de React en HTML y CSS estáticos. De esta manera, el contenido inicial se puede servir desde un CDN, y luego Next puede "hidratar" la página para hacer que los elementos sean dinámicos. Una vez que la página está hidratada, nuestro sitio se convierte en una aplicación de una sola página donde las personas pueden buscar y generar nombres de dominio. No confiamos en Next.js para hacer mucho trabajo del lado del servidor, la mayoría de nuestro contenido se exporta estáticamente como HTML, CSS y JavaScript para servir desde un CDN.
Cuando alguien comienza a buscar un nombre de dominio, reemplazamos el contenido de la página con resultados de búsqueda. Para que las búsquedas sean lo más rápidas posible, el front-end consulta directamente nuestro backend de Rust, que está muy optimizado para búsquedas y sugerencias de dominios. Muchas consultas las podemos responder instantáneamente, pero para algunos TLD necesitamos hacer consultas de DNS más lentas que pueden tardar uno o dos segundos en resolverse. Cuando se resuelvan algunas de estas consultas más lentas, actualizaremos la interfaz de usuario con cualquier información nueva que ingrese. Las páginas de resultados son diferentes para todos, y puede ser difícil para nosotros predecir exactamente cómo cada persona experimenta el sitio.
Las Chrome DevTools son excelentes y un buen lugar para comenzar cuando se buscan problemas de rendimiento. La vista Rendimiento muestra exactamente cuándo salen las solicitudes HTTP, dónde el navegador dedica tiempo a evaluar JavaScript y más:
Hay tres métricas de Core Web Vitals que Google utilizará para ayudar a clasificar los sitios en su próxima actualización del algoritmo de búsqueda. Google clasifica las experiencias en "Bueno", "Necesita mejorar" y "Deficiente" en función de los puntajes LCP, FID y CLS que las personas reales tienen en el sitio:
- LCP , o Largest Contentful Paint, define el tiempo que tarda en hacerse visible el elemento de contenido más grande.
- FID , o First Input Delay, se relaciona con la capacidad de respuesta de un sitio a la interacción: el tiempo entre un toque, un clic o una pulsación de tecla en la interfaz y la respuesta de la página.
- CLS , o Cambio de diseño acumulativo, rastrea cómo los elementos se mueven o cambian en la página sin acciones como un teclado o un evento de clic.
Chrome está configurado para realizar un seguimiento de estas métricas en todos los usuarios de Chrome que han iniciado sesión y envía estadísticas anónimas que resumen la experiencia de un cliente en un sitio a Google para su evaluación. Se puede acceder a estos puntajes a través del Informe de experiencia del usuario de Chrome y se muestran cuando inspecciona una URL con la herramienta PageSpeed Insights. Los puntajes representan la experiencia del percentil 75 para las personas que visitaron esa URL durante los 28 días anteriores. Este es el número que usarán para ayudar a clasificar los sitios en la actualización.
Una métrica del percentil 75 (p75) logra un equilibrio razonable para los objetivos de rendimiento. Tomar un promedio, por ejemplo, ocultaría muchas malas experiencias que tiene la gente. La mediana, o percentil 50 (p50), significaría que la mitad de las personas que usaban nuestro producto estaban teniendo una peor experiencia. El percentil 95 (p95), por otro lado, es difícil de construir, ya que captura demasiados valores atípicos extremos en dispositivos antiguos con conexiones irregulares. Creemos que la puntuación basada en el percentil 75 es un estándar justo que cumplir.
Para tener nuestros puntajes bajo control, primero recurrimos a Lighthouse para obtener excelentes herramientas integradas en Chrome y alojadas en web.dev/measure/, y en PageSpeed Insights. Estas herramientas nos ayudaron a encontrar algunos problemas técnicos generales con nuestro sitio. Vimos que la forma en que Next.js agrupaba nuestro CSS y ralentizaba nuestro tiempo de renderizado inicial, lo que afectaba a nuestro FID. La primera victoria fácil provino de una característica experimental de Next.js,OptimizeCss, que ayudó a mejorar significativamente nuestra puntuación de rendimiento general.
Lighthouse también detectó una configuración incorrecta de caché que impidió que algunos de nuestros activos estáticos se sirvieran desde nuestra CDN. Estamos alojados en Google Cloud Platform, y Google Cloud CDN requiere que el encabezado Cache-Control contenga "público". Next.js no le permite configurar todos los encabezados que emite, por lo que tuvimos que anularlos colocando el servidor Next.js detrás de Caddy, un servidor proxy HTTP liviano implementado en Go. También aprovechamos la oportunidad para asegurarnos de que estábamos sirviendo lo que podíamos con el soporte relativamente nuevo obsoleto mientras se revalida en los navegadores modernos que permite que la CDN obtenga contenido del origen (nuestro servidor Next.js) de forma asincrónica en segundo plano.
Es fácil, quizás demasiado fácil, agregar casi cualquier cosa que necesite a su producto desde npm. El tamaño de los paquetes no tarda mucho en crecer. Los paquetes grandes tardan más en descargarse en redes lentas, y el teléfono móvil del percentil 75 pasará mucho tiempo bloqueando el hilo principal de la interfaz de usuario mientras intenta dar sentido a todo el código que acaba de descargar. Nos gustó BundlePhobia, que es una herramienta gratuita que muestra cuántas dependencias y bytes agregará un paquete npm a su paquete. Esto nos llevó a eliminar o reemplazar una serie de animaciones impulsadas por resortes reactivos con transiciones CSS más simples:
Mediante el uso de BundlePhobia y Lighthouse, descubrimos que el software de análisis y registro de errores de terceros contribuyó significativamente al tamaño de nuestro paquete y al tiempo de carga. Eliminamos y reemplazamos estas herramientas con nuestro propio registro del lado del cliente que aprovecha las API de los navegadores modernos como sendBeacon y ping. Enviamos registros y análisis a nuestra propia infraestructura de Google BigQuery, donde podemos responder las preguntas que nos interesan con más detalle que cualquiera de las herramientas disponibles en el mercado. Esto también elimina una serie de cookies de terceros y nos da mucho más control sobre cómo y cuándo enviamos los datos de registro de los clientes.
Nuestro puntaje CLS aún tenía más margen de mejora. La forma en que Google calcula CLS es complicada: se le da una "ventana de sesión" máxima con un intervalo de 1 segundo, con un límite de 5 segundos desde la carga de la página inicial, o desde una interacción de teclado o clic, para terminar de mover las cosas por el sitio. . Si está interesado en leer más profundamente sobre este tema, aquí hay una gran guía sobre el tema. Esto penaliza muchos tipos de superposiciones y ventanas emergentes que aparecen justo después de aterrizar en un sitio. Por ejemplo, los anuncios que cambian el contenido o las ventas adicionales que pueden aparecer cuando comienza a desplazarse por los anuncios para llegar al contenido. Este artículo proporciona una excelente explicación de cómo se calcula la puntuación CLS y el razonamiento detrás de ella.
Nos oponemos fundamentalmente a este tipo de desorden digital, por lo que nos sorprendió ver cuánto margen de mejora insistió Google en hacer. Chrome tiene una superposición de Web Vitals incorporada a la que puede acceder usando el menú de comandos para "Mostrar superposición de Core Web Vitals". Para ver exactamente qué elementos considera Chrome en su cálculo de CLS, encontramos más útil la opción "Registro de consola" de la extensión Chrome Web Vitals en la configuración. Una vez habilitado, este complemento muestra sus puntajes LCP, FID y CLS para la página actual. Desde la consola, puede ver exactamente qué elementos de la página están conectados a estas partituras. Nuestros puntajes CLS tenían la mayor cantidad de espacio para mejorar.
De las tres métricas, CLS es la única que se acumula a medida que interactúa con una página. La extensión Web Vitals tiene una opción de registro que mostrará exactamente qué elementos causan CLS mientras interactúa con un producto. Mire cómo se agregan las métricas de CLS cuando nos desplazamos en la página de inicio de Smashing Magazine:
Google continuará ajustando la forma en que calcula CLS con el tiempo, por lo que es importante mantenerse informado siguiendo el blog de desarrollo web de Google. Al usar herramientas como la extensión Chrome Web Vitals, es importante habilitar la aceleración de la CPU y la red para obtener una experiencia más realista. Puede hacerlo con las herramientas de desarrollo simulando una CPU móvil.
La mejor manera de realizar un seguimiento del progreso de una implementación a la siguiente es medir las experiencias de la página de la misma manera que lo hace Google. Si tiene configurado Google Analytics, una manera fácil de hacerlo es instalar el módulo web-vitals de Google y conectarlo a Google Analytics. Esto proporciona una medida aproximada de su progreso y lo hace visible en un panel de control de Google Analytics.
Aquí es donde chocamos contra una pared. Pudimos ver nuestra puntuación CLS y, aunque la habíamos mejorado significativamente, todavía teníamos trabajo por hacer. Nuestro puntaje CLS fue de aproximadamente 0,23 y necesitábamos bajarlo por debajo de 0,1, y preferiblemente hasta 0. En este punto, sin embargo, no pudimos encontrar algo que nos dijera exactamente qué componentes en qué páginas seguían afectando el puntaje. Pudimos ver que Chrome expuso muchos detalles en sus herramientas Core Web Vitals, pero que los agregadores de registro descartaron la parte más importante: exactamente qué elemento de la página causó el problema.
Para capturar todos los detalles que necesitamos, creamos una función sin servidor para capturar datos vitales web de los navegadores. Dado que no necesitamos ejecutar consultas en tiempo real sobre los datos, los transmitimos a la API de transmisión de Google BigQuery para su almacenamiento. Esta arquitectura significa que podemos capturar de forma económica tantos puntos de datos como podamos generar.
Después de aprender algunas lecciones mientras trabajábamos con Web Vitals y BigQuery, decidimos agrupar esta funcionalidad y lanzar estas herramientas como código abierto en vitals.dev.
El uso de Instant Vitals es una forma rápida de comenzar a realizar un seguimiento de sus puntajes de Web Vitals en BigQuery. Este es un ejemplo de un esquema de tabla de BigQuery que creamos:
La integración con Instant Vitals es fácil. Puede comenzar integrándose con la biblioteca del cliente para enviar datos a su backend o función sin servidor:
import { init } from "@instantdomain/vitals-client"; init({ endpoint: "/api/web-vitals" });
Luego, en su servidor, puede integrarse con la biblioteca del servidor para completar el circuito:
import fs from "fs"; import { init, streamVitals } from "@instantdomain/vitals-server"; // Google libraries require service key as path to file const GOOGLE_SERVICE_KEY = process.env.GOOGLE_SERVICE_KEY; process.env.GOOGLE_APPLICATION_CREDENTIALS = "/tmp/goog_creds"; fs.writeFileSync( process.env.GOOGLE_APPLICATION_CREDENTIALS, GOOGLE_SERVICE_KEY ); const DATASET_; init({ datasetId: DATASET_ID }).then().catch(console.error); // Request handler export default async (req, res) => { const body = JSON.parse(req.body); await streamVitals(body, body.name); res.status(200).end(); };
Simplemente llame a streamVitals
con el cuerpo de la solicitud y el nombre de la métrica para enviar la métrica a BigQuery. La biblioteca se encargará de crear el conjunto de datos y las tablas por usted.
Después de recopilar los datos de un día, ejecutamos esta consulta como esta:
SELECT `<project_name>.web_vitals.CLS`.Value, Node FROM `<project_name>.web_vitals.CLS` JOIN UNNEST(Entries) AS Entry JOIN UNNEST(Entry.Sources) WHERE Node != "" ORDER BY value LIMIT 10
Esta consulta produce resultados como este:
Valor | Nodo |
---|---|
4.6045324800736724E-4 | /html/body/div[1]/main/div/div/div[2]/div/div/blockquote |
7.183070668914928E-4 | /html/body/div[1]/header/div/div/header/div |
0.031002668277977697 | /html/body/div[1]/footer |
0.035830703317463526 | /html/body/div[1]/main/div/div/div[2] |
0.035830703317463526 | /html/body/div[1]/footer |
0.035830703317463526 | /html/body/div[1]/main/div/div/div[2] |
0.035830703317463526 | /html/body/div[1]/main/div/div/div[2] |
0.035830703317463526 | /html/body/div[1]/footer |
0.035830703317463526 | /html/body/div[1]/footer |
0.03988482067913317 | /html/body/div[1]/footer |
Esto nos muestra qué elementos en qué páginas tienen el mayor impacto en CLS. Creó una lista de problemas para que nuestro equipo la investigara y la arreglara. En Instant Domain Search, resulta que las conexiones móviles lentas o malas tardarán más de 500 ms en cargar algunos de nuestros resultados de búsqueda. Uno de los peores contribuyentes a CLS para estos usuarios fue en realidad nuestro pie de página.
El puntaje de cambio de diseño se calcula como una función del tamaño del elemento que se mueve y qué tan lejos llega. En nuestra vista de resultados de búsqueda, si un dispositivo tarda más de una cierta cantidad de tiempo en recibir y mostrar los resultados de búsqueda, la vista de resultados se colapsaría a una zero-height
mostraría el pie de página. Cuando llegan los resultados, empujan el pie de página hacia la parte inferior de la página. Un gran elemento DOM que se movió tan lejos agregó mucho a nuestro puntaje CLS. Para resolver esto correctamente, necesitamos reestructurar la forma en que se recopilan y representan los resultados de la búsqueda. Decidimos simplemente eliminar el pie de página en la vista de resultados de búsqueda como un truco rápido que evitaría que rebotara en conexiones lentas.
Ahora revisamos este informe regularmente para hacer un seguimiento de cómo estamos mejorando y lo usamos para combatir la disminución de los resultados a medida que avanzamos. Hemos sido testigos del valor de la atención adicional a las funciones y productos recién lanzados en nuestro sitio y hemos puesto en práctica controles consistentes para asegurarnos de que los elementos vitales principales estén actuando a favor de nuestra clasificación. Esperamos que al compartir Instant Vitals podamos ayudar a otros desarrolladores a abordar sus puntajes de Core Web Vitals también.
Google proporciona excelentes herramientas de rendimiento integradas en Chrome, y las usamos para encontrar y solucionar una serie de problemas de rendimiento. Aprendimos que los datos de campo proporcionados por Google ofrecían un buen resumen de nuestro progreso de p75, pero no tenían detalles procesables. Necesitábamos averiguar exactamente qué elementos DOM estaban causando cambios de diseño y retrasos en la entrada. Una vez que comenzamos a recopilar nuestros propios datos de campo, con consultas XPath, pudimos identificar oportunidades específicas para mejorar la experiencia de todos en nuestro sitio. Con un poco de esfuerzo, redujimos nuestras puntuaciones de campo de Core Web Vitals del mundo real a un rango aceptable en preparación para la actualización de la experiencia de la página de junio. ¡Nos alegra ver que estos números van hacia abajo y hacia la derecha!