Resolución de problemas de CLS en un sitio web de comercio electrónico impulsado por Next.js (estudio de caso)
Publicado: 2022-03-10Fairprice es una de las tiendas de comestibles en línea más grandes de Singapur. Buscamos continuamente áreas de oportunidad para mejorar la experiencia de compra en línea del usuario. El rendimiento es uno de los aspectos centrales para garantizar que nuestros usuarios tengan una experiencia de usuario agradable, independientemente de sus dispositivos o conexión de red.
Hay muchos indicadores clave de rendimiento (KPI) que miden diferentes puntos durante el ciclo de vida de la página web (como TTFB, domInteractive
y onload
), pero estas métricas no reflejan cómo el usuario final experimenta la página.
Queríamos usar algunos KPI que se correspondan estrechamente con la experiencia real de los usuarios finales para que sepamos que si alguno de esos KPI no funciona bien, tendrá un impacto directo en la experiencia del usuario final. Descubrimos que las métricas de rendimiento centradas en el usuario son perfectas para este propósito.
Hay muchas métricas de rendimiento centradas en el usuario para medir diferentes puntos en el ciclo de vida de una página, como FCP, LCP, FID, CLS, etc. Para este estudio de caso, nos centraremos principalmente en CLS.
CLS mide la puntuación total de todos los cambios de diseño inesperados que ocurren desde que la página comienza a cargarse hasta que se descarga.
“
Por lo tanto, tener un valor CLS bajo para una página garantiza que no haya cambios de diseño aleatorios que provoquen la frustración del usuario. Barry Pollard ha escrito un excelente artículo detallado sobre CLS.
Cómo descubrimos el problema de CLS en nuestra página de productos
Usamos Lighthouse y WebPagetest como nuestras herramientas de prueba sintéticas para medir el rendimiento de CLS. También usamos la biblioteca web-vitals para medir CLS para usuarios reales. Aparte de eso, revisamos la sección Informe principal de Web Vitals de Google Search Console para tener una idea de cualquier problema potencial de CLS en cualquiera de nuestras páginas. Al explorar la sección de informes, encontramos que muchas URL de la página de detalles del producto tenían un valor CLS de más de 0,1 , lo que sugiere que allí se está produciendo un cambio de diseño importante.
Depuración de problemas de CLS con diferentes herramientas
Ahora que sabemos que hay un problema de CLS en la página de detalles del producto, el siguiente paso fue identificar qué elemento lo estaba causando. Al principio, decidimos ejecutar algunas pruebas con herramientas de prueba sintéticas.
Así que ejecutamos el faro para verificar si podía encontrar algún elemento que pudiera desencadenar un cambio de diseño importante, informó CLS a .004, que es bastante bajo.
La página de informe de Lighthouse tiene una sección de diagnóstico. Eso tampoco mostró ningún elemento que causara un valor alto de CLS.
Luego ejecutamos WebpageTest y decidimos verificar la vista de tira de película:
Encontramos esta función muy útil ya que podemos averiguar qué elemento en qué momento provocó que el diseño cambiara. Pero cuando ejecutamos la prueba para ver si se resalta algún cambio de diseño, no hubo nada que contribuyera al enorme LCS:
La peculiaridad de CLS es que registra las puntuaciones de cambio de diseño individuales durante toda la vida útil de la página y las agrega.
“
Nota : La forma en que se mide CLS ha cambiado desde junio de 2021.
Dado que Lighthouse y WebpageTest no pudieron detectar ningún elemento que desencadenara un cambio importante en el diseño, lo que significa que estaba ocurriendo después de la carga inicial de la página, posiblemente debido a alguna acción del usuario. Así que decidimos usar la extensión de Google Chrome Web Vitals, ya que puede registrar CLS en una página mientras el usuario interactúa con ella. Después de realizar diferentes acciones, descubrimos que la puntuación de cambio de diseño aumenta cuando el usuario usa la función de ampliación de imagen.
Para verificar si se está produciendo un cambio de diseño mientras el mouse está sobre la imagen, usamos el siguiente fragmento de código de https://web.dev/cls/ que agrega console.log
cuando se produce un cambio de diseño:
let cls = 0; new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { if (!entry.hadRecentInput) { cls += entry.value; console.log('Current CLS value:', cls, entry); } }}).observe({type: 'layout-shift', buffered: true});
En una investigación más profunda, encontramos que ASDA enfrentó un tipo de problema similar y lo planteó para Chrome.
Causa principal
En la página de detalles del producto, los usuarios pueden mover el mouse sobre la imagen del producto para ver una sección ampliada de la imagen al lado de la imagen real del producto, ya que este video muestra exactamente de lo que estamos hablando.
La función de ampliación de imagen ayuda a nuestros usuarios a obtener la apariencia del producto y a garantizar que sea la variante correcta del producto que desean comprar.
Hemos utilizado la biblioteca de react-image zoom
para construir esta funcionalidad de ampliación de imagen.
Las bibliotecas de ampliación de imágenes suelen tener una lente (un cuadrado que se mueve cuando el mouse se mueve dentro de la imagen). Dado que esta lente cambia su posición superior e izquierda con el movimiento del mouse, se detecta como un cambio de diseño que activa CLS. Verificamos la página de la biblioteca, así como otras bibliotecas de reacción similares ( react-image-magnify
, react-image-zoom
, react-image-magnifiers
) y descubrimos que todas ellas sufren el mismo problema de CLS.
Cómo lo solucionamos
Notamos que react-image-zoom
estaba usando la biblioteca js-image-zoom
. Así que tuvimos que modificar la biblioteca de js-image zoom
para solucionar el problema.
La solución es bastante sencilla. Mientras el mouse se mueve sobre la imagen del producto, el elemento de la lente de la imagen se mueve cambiando su posición izquierda y superior. Para solucionar el problema, usamos transform translate
, que mueve el elemento a una nueva capa, es decir, cualquier movimiento que tenga lugar en esta nueva capa ya no provoca cambios en el diseño:
También creé un PR para el repositorio original para que otros desarrolladores que usan esta biblioteca puedan deshacerse del problema de CLS.
El impacto del cambio
Después de que el código se implementó en producción, el CLS se arregló en la página de detalles del producto y la cantidad de páginas afectadas con CLS se redujo en un 98 %:
Dado que usamos transform
, también ayudó a que la imagen se ampliara y una experiencia más fluida para los usuarios.
Nota : Paul Irish ha escrito un excelente artículo sobre este tema.
Otros cambios clave que hicimos para CLS
También hay otros problemas que enfrentamos a través de muchas páginas en nuestro sitio web que contribuyen a CLS. Repasemos esos elementos y componentes y veamos cómo tratamos de mitigar los cambios de diseño que surgen de ellos.
Fuentes web:
Nos hemos dado cuenta de que la carga tardía de las fuentes provoca frustraciones en los usuarios, ya que el contenido parpadea y también provoca una cierta cantidad de cambios en el diseño. Para minimizar esto, hemos hecho algunos cambios:- Hemos autohospedado las fuentes en lugar de cargarlas desde CDN de terceros.
- Precargamos las fuentes.
- Usamos font-display opcional.
Imágenes:
La falta de valor de altura o ancho en la imagen hace que el elemento después de la imagen se desplace una vez que se carga la imagen. Esto termina convirtiéndose en un importante contribuyente a CLS. Como usamos Next.js, aprovechamos el componente de imagen integrado llamadonext/images
. Este componente incorpora varias prácticas recomendadas relacionadas con imágenes. Está construido sobre la etiqueta HTML<img>
y puede ayudar a mejorar LCP y CLS. Recomiendo encarecidamente leer este RFC para conocer las características clave y las ventajas de usarlo.Scroll infinito:
En nuestro sitio web, las páginas de listado de productos tienen un desplazamiento infinito. Entonces, inicialmente, cuando los usuarios se desplazan hasta la parte inferior de la página, ven un pie de página durante una fracción de segundo antes de que se cargue el siguiente conjunto de datos, lo que provoca cambios en el diseño. Para resolver esto tomamos algunos pasos:- Llamamos a la API para cargar datos incluso antes de que el usuario llegue al final absoluto de la lista.
- Hemos reservado suficiente espacio para el estado de carga y mostramos esqueletos de productos durante el estado de carga. Ahora, cuando el usuario se desplaza, no ve el pie de página durante una fracción de segundo mientras se cargan los productos.
Addy Osmani ha escrito un artículo detallado sobre este enfoque que recomiendo consultar.
Conclusiones clave
- Si bien Lighthouse y WebpageTest ayudan a descubrir problemas de rendimiento que ocurren hasta que se carga la página, no pueden detectar problemas de rendimiento después de la carga de la página.
- Las extensiones de Web Vitals pueden detectar cambios de CLS provocados por las interacciones del usuario, por lo que si una página tiene un valor de CLS alto pero Lighthouse o WebpageTest informan un CLS bajo, la extensión de Web Vitals puede ayudar a identificar el problema.
- Los datos de Google Search Console se basan en datos de usuarios reales, por lo que también pueden señalar posibles problemas de rendimiento que ocurren en cualquier punto del ciclo de vida de una página. Una vez que se detecta y soluciona un problema, verificar nuevamente la sección del informe puede ayudar a verificar la efectividad de la corrección de rendimiento. Los cambios se reflejan en cuestión de días en la sección de informes web vitals.
Pensamientos finales
Si bien los problemas de CLS son comparativamente más difíciles de depurar, el uso de una combinación de diferentes herramientas hasta la carga de la página (Lighthouse, WebPageTest) y la extensión Web Vitals (después de la carga de la página) puede ayudarnos a identificar el problema. También es una de las métricas que está experimentando un gran desarrollo activo para cubrir una amplia gama de escenarios y esto significa que la forma en que se mide cambiará en el futuro. Seguimos https://web.dev/evolving-cls/ para conocer los próximos cambios.
En cuanto a nosotros, también trabajamos continuamente para mejorar otros Core Web Vitals. Recientemente, implementamos la precarga de imágenes receptivas y comenzamos a publicar imágenes en formato WebP, lo que nos ayudó a reducir el 75 % de la carga de imágenes, reducir el LCP en un 62 % y el índice de velocidad en un 24 %. Puede leer más detalles de optimización para mejorar LCP y Speed Index o seguir nuestro blog de ingeniería para conocer otros trabajos interesantes que estamos realizando.
Nos gustaría agradecer a Alex Castle por ayudarnos a depurar el problema de CLS en la página del producto y resolver las peculiaridades en la implementación next/images
.