Cómo Trendyol redujo el INP en un 50%, lo que generó un aumento del 1% en la tasa de clics

En este caso de éxito, se describe un flujo de trabajo paso a paso para depurar y mejorar la INP en React que usa Trendyol aprovechando las herramientas de Google, como PageSpeed Insights (PSI), Herramientas para desarrolladores de Chrome y la API de scheduler.yield.

Dos componentes fundamentales de cualquier sitio web de comercio electrónico son la página de fichas de productos (PLP) y la página de detalles del producto (PDP). El tráfico de comercio electrónico suele provenir de las páginas de fichas de productos, ya sea a través de campañas por correo electrónico, redes sociales o anuncios. Como resultado, es fundamental garantizar que la experiencia de la PLP esté diseñada con cuidado para reducir el tiempo que se tarda en realizar una compra. Priorizar la calidad de la experiencia del usuario es esencial para lograr el éxito. Publicaciones de investigación como Milliseconds Make Millions ya revelaron el impacto significativo del rendimiento web en la disposición de los consumidores de invertir dinero e interactuar con las marcas en línea.

Trendyol es una plataforma de comercio electrónico con alrededor de 30 millones de clientes y 240,000 vendedores, lo que nos llevó a convertirnos en la primera empresa de Turquía con una valoración de más de USD 10,000 millones y una de las principales plataformas de comercio electrónico del mundo.

Para lograr su objetivo de proporcionar la mejor experiencia del usuario posible a gran escala y, al mismo tiempo, mantener la flexibilidad del contenido y trabajar con una versión anterior de React, Trendyol se enfocó en Interaction to Next Paint (INP) como una métrica clave para mejorar. En este caso de éxito, se describe el recorrido de Trendyol para mejorar la INP en su PLP, lo que generó una reducción del 50% de la INP y un aumento del 1% en la métrica empresarial de resultados de la búsqueda.

Proceso de investigación de INP de Trendyol

La INP mide la capacidad de respuesta de un sitio web ante las entradas del usuario. Una buena INP indica que el navegador puede responder de forma rápida y confiable a todas las entradas del usuario y volver a pintar la página, lo que es un componente clave de una buena experiencia del usuario.

El recorrido de Trendyol para mejorar la INP en su PLP comenzó con un análisis exhaustivo de la experiencia del usuario antes de realizar cualquier mejora. Según un informe de PSI, la experiencia real del usuario de la PLP tuvo un INP de 963 milisegundos en dispositivos móviles, como se muestra en la siguiente imagen.

INP de Trendyol según la lectura de CrUX en PageSpeed Insights. El INP de Trendyol al 5 de septiembre de 2023 fue de 963 milisegundos, que se encuentra en el rango "deficiente".
INP de Trendyol al 5 de septiembre de 2023 de PSI.

Para garantizar una buena capacidad de respuesta, los propietarios de sitios deben apuntar a un INP inferior o igual a 200 milisegundos, lo que significa que, en ese momento, el INP de Trendyol estaba en el rango "deficiente".

Afortunadamente, PSI proporciona datos de campo para las páginas incluidas en el Informe de experiencia del usuario de Chrome (CrUX) y datos detallados de diagnóstico de lab. Al observar los datos del laboratorio, la auditoría del tiempo de ejecución de JavaScript de Lighthouse sugirió que la secuencia de comandos search-result-v2 estaba ocupando el subproceso principal durante más tiempo que otras secuencias de comandos de la página.

Lectura de las fuentes de tareas largas en Lighthouse para el sitio web de Trendyol. Una de las principales fuentes de tareas largas es una secuencia de comandos que controla los resultados de la búsqueda en el PLP de Trendyol.
La auditoría del tiempo de ejecución de JavaScript de Lighthouse de Trendyol al 5 de septiembre de 2023 de PSI.

Para identificar los cuellos de botella del mundo real, usamos el panel de rendimiento en DevTools de Chrome para solucionar problemas relacionados con la experiencia de PLP y detectar la fuente del problema. La emulación del rendimiento de los dispositivos móviles con una ralentización de la CPU de 4 veces en Chrome DevTools reveló una tarea de 700 a 900 milisegundos de duración en el subproceso principal. Si el subproceso principal está ocupado con otras tareas durante más de 50 milisegundos, es posible que no pueda responder a la entrada del usuario de manera oportuna, lo que provocaría una mala experiencia del usuario.

Captura de pantalla de una sesión de generación de perfiles de rendimiento en Chrome DevTools para el PLP de Trendyol. La tarea larga representada se ejecuta durante 737.6 milisegundos y forma parte de una devolución de llamada de Intersection Observer.
Generador de perfiles de rendimiento de tareas largas en el PLP de Trendyol en el panel de rendimiento de Chrome DevTools.

La tarea más larga fue causada por una devolución de llamada de la API de Intersection Observer en la secuencia de comandos de resultados de la búsqueda dentro de un componente de React. En este punto, comenzamos a analizar la posibilidad de dividir esa tarea larga en fragmentos pequeños para darle al navegador más oportunidades de responder a tareas de mayor prioridad, incluidas las interacciones del usuario.

Resulta que usar la operación setState que activa la renderización de React dentro de la devolución de llamada de Intersection Observer tiene un costo alto, lo que puede causar problemas para dispositivos de gama baja, ya que ocupa el subproceso principal durante demasiado tiempo.

Un método que los desarrolladores usaron para dividir tareas en otras más pequeñas implica setTimeout. Usamos esta técnica para posponer la ejecución de la llamada a setState en una tarea separada. Aunque setTimeout permite aplazar la ejecución de JavaScript, no proporciona ningún control sobre la prioridad. Esto nos llevó a unirnos a la prueba de origen scheduler.yield para garantizar la continuación de la ejecución de nuestra secuencia de comandos después de ceder al subproceso principal:

/*
* Yielding method using scheduler.yield, falling back to setTimeout:
*/
async function yieldToMain() {
  if('scheduler' in window && 'yield' in scheduler) {
    return await scheduler.yield();
  }

  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}

/*
* Yielding to the main thread before changing the state of the component:
*/
const observer = new IntersectionObserver((entries) => {
  entries.forEach(handleIntersection);
  const maxNumberOfEntries = Math.max(...this.intersectingEntries);

  if (Number.isFinite(maxNumberOfEntries)) {
    await this.yieldToMain();

    this.setState({ count: maxNumberOfEntries });
  }
}, { threshold: 0.5 });

Agregar este método de entrega al código de PLP mejoró el INP, ya que la tarea larga principal se dividió en una serie de tareas más pequeñas, lo que permite que el trabajo de mayor prioridad, como las interacciones del usuario y el trabajo de renderización posterior, se realice antes de lo que lo haría de otra manera.

Captura de pantalla de una sesión de generación de perfiles de rendimiento en Chrome DevTools para el PLP de Trendyol. La tarea larga que antes se ejecutaba durante 737.6 milisegundos ahora se divide en varias tareas más pequeñas.
La tarea se divide en tareas más pequeñas.

Ten en cuenta que Trendyol usa el framework PuzzleJs para implementar una arquitectura de micro-frontend con React v16.9.0. Con React 18, se podría lograr el mismo rendimiento, pero, por varios motivos, Trendyol no puede actualizar en este momento.

Resultados empresariales

Para medir el impacto de la mejora de INP implementada, ejecutamos una prueba A/B para ver cómo se vieron afectadas las métricas empresariales. En general, nuestros cambios en la PLP generaron una mejora significativa, incluida una reducción del 50% de la INP y un aumento del 1% en las tasas de clics de la página de fichas a la página de detalles del producto por sesión del usuario. En la siguiente figura, puedes ver cómo mejoró la INP en el PLP a lo largo del tiempo:

Captura de pantalla del INP del percentil 75 de Trendyol a lo largo de seis meses. Al final de los seis meses, el INP de Trendyol disminuyó a casi 650 milisegundos desde casi 1,400 milisegundos.
Mejoras en el INP del percentil 75 a lo largo del tiempo.

Conclusión

La optimización de la INP es un proceso complejo e iterativo, pero se puede facilitar con un flujo de trabajo claro. Un enfoque simple para depurar y mejorar el INP de tu sitio web depende de si recopilas tus propios datos de campo. Si no es así, PSI y Lighthouse son un buen punto de partida. Una vez que hayas identificado las páginas con problemas, puedes usar DevTools para profundizar y tratar de reproducir los problemas.

Si cedes el subproceso principal de vez en cuando para darle al navegador más oportunidades de realizar tareas urgentes, tu sitio web será más responsivo, lo que garantizará que tus clientes tengan una mejor experiencia del usuario. Las APIs de programación más nuevas, como scheduler.yield(), facilitan esta tarea.

Agradecimientos especiales a Jeremy Wagner, Barry Pollard y Houssein Djirdeh de Google, y al equipo de Ingeniería de Trendyol por su contribución a este trabajo.