Identifica las causas de una INP deficiente

La mala capacidad de respuesta a las interacciones genera una mala impresión de que una página es lenta o incluso está completamente rota. Interaction to Next Paint (INP) es una métrica basada en la API de Event Timing. Mide la peor interacción (menos algunos valores atípicos) como una medida de la capacidad de respuesta de la página.

Identificar las causas raíz de una página web que no responde puede ser difícil, especialmente porque depende de las interacciones del usuario y de las condiciones del entorno, como las capacidades del dispositivo y las condiciones de la red. Esto hace que sea aún más difícil de diagnosticar en comparación con una situación más repetible y predecible, como la carga de página. Los datos de lab solo replican un pequeño subconjunto de situaciones de usuarios reales, por lo que es esencial medir las causas de la INP lenta en el campo.

La API de Event Timing permite dividir la duración de la INP en tres partes: retraso de entrada (procesamiento que ya se está realizando cuando se produce la interacción), duración del procesamiento (retrasos que se producen como resultado directo de la interacción) y retraso de presentación (retrasos que se deben a la renderización del siguiente fotograma después de la interacción). Esto ayuda a identificar si el problema está en otro código, en el código JavaScript de interacción o en las actualizaciones de renderización del procesamiento del navegador, respectivamente, en lugar de saltar directamente al código de interacción.

Es posible recopilar más información sobre JavaScript, el recálculo de diseño y el trabajo de diseño que retrasan una interacción. Un seguimiento de rendimiento completo con la API de JS Self-Profiling es una solución pesada que puede causar problemas de rendimiento. La API de Long Animation Frames es una API ligera que se puede usar en el campo para identificar el código de JavaScript que se ejecuta con lentitud y distinguir entre los costos de actualización de diseño y de actualización de diseño durante las interacciones de INP:

  • Estilo y diseño forzados a nivel de la secuencia de comandos (forcedStyleDuration y forcedLayoutDuration): Informa los nuevos cálculos de estilo síncronos (como llamar a getComputedStyle() después de las mutaciones del DOM) y los diseños o redistribuciones forzados (como leer getBoundingClientRect() o offsetWidth después de las mutaciones) dentro de una secuencia de comandos en ejecución durante la Demora de entrada o la Duración del procesamiento.
  • Estilo y diseño de renderización a nivel del fotograma (styleDuration y layoutDuration): Informa el tiempo que se dedica a volver a calcular los estilos en comparación con la actualización del diseño durante la actualización de la renderización del fotograma, lo que ayuda a explicar la demora de presentación alta.

Distinguir el nuevo cálculo de estilo del diseño es fundamental porque tienen diferentes causas raíz y soluciones: una duración de estilo alta indica una coincidencia de selector CSS costosa o una invalidación de estilo amplia (se soluciona simplificando los selectores o reduciendo el alcance de las reglas), mientras que una duración de diseño alta indica cálculos de geometría costosos o una destrucción de diseño síncrona (se soluciona agrupando las lecturas del DOM antes de las escrituras, simplificando la estructura del DOM o usando la contención de CSS).

Cómo implementarlo

Calcular la INP a partir de la API de Event Timing sin procesar es complicado y tiene varios matices. Te recomendamos que uses una herramienta o biblioteca de RUM para recopilar estos datos.

web-vitals es una biblioteca de código abierto de Google que calcula las métricas de Core Web Vitals, incluida la INP, y también incluye datos de subpartes y fotogramas de animación largos para la interacción de INP.

Obtén atribuciones para las interacciones de INP con la biblioteca web-vitals

La biblioteca web-vitals es una biblioteca pequeña que se usa para medir las Métricas web esenciales y otras métricas de rendimiento. La función onINP() se puede usar para identificar la interacción más lenta y, además, incluye información sobre las subpartes de INP, las secuencias de comandos que se ejecutaron durante la interacción y las duraciones de estilo y diseño con la API de Long Animation Frames.

// Use the attribution build to get Long Animation Frame data
// alongside the INP metric value.
import { onINP } from 'web-vitals/attribution';

onINP((metric) => {
  const { attribution } = metric;
  const longestScript = attribution.longestScript;

  // Sum rendering-phase style and layout durations across all LoAF entries
  // intersecting the INP interaction (primarily explains presentationDelay).
  let renderStyleDuration = 0;
  let renderLayoutDuration = 0;
  for (const entry of attribution.longAnimationFrameEntries) {
    renderStyleDuration += entry.styleDuration ?? 0;
    renderLayoutDuration += entry.layoutDuration ?? 0;
  }

  // Beacon script, style, and layout attribution for the INP interaction,
  // so you can identify the root cause in production.
  navigator.sendBeacon(
    '/analytics',
    JSON.stringify({
      name: 'INP',
      value: metric.value,
      // These fields give the INP subparts:
      inputDelay: attribution.inputDelay,
      presentationDelay: attribution.presentationDelay,
      processingDuration: attribution.processingDuration,
      interactionTarget: attribution.interactionTarget,
      // These fields identify which script function was responsible
      // for the longest processing during the INP interaction.
      invokerType: longestScript?.entry?.invokerType,
      sourceURL: longestScript?.entry?.sourceURL,
      sourceFunctionName: longestScript?.entry?.sourceFunctionName,
      sourceCharPosition: longestScript?.entry?.sourceCharPosition,
      // subpart indicates which phase (input delay, processing, or
      // presentation delay) the longest script overlapped with most.
      subpart: longestScript?.subpart,
      intersectingDuration: longestScript?.intersectingDuration,
      // Synchronous style and layout work forced inside the longest script
      // (with forcedStyleAndLayoutDuration as a combined fallback):
      forcedStyleDuration: longestScript?.entry?.forcedStyleDuration,
      forcedLayoutDuration: longestScript?.entry?.forcedLayoutDuration,
      forcedStyleAndLayoutDuration: longestScript?.entry?.forcedStyleAndLayoutDuration,
      // Rendering-phase style and layout work across the interaction's frames
      // (with totalStyleAndLayoutDuration as a combined fallback):
      renderStyleDuration,
      renderLayoutDuration,
      totalStyleAndLayoutDuration: attribution.totalStyleAndLayoutDuration
    })
  );
});

Prácticas recomendadas

  • SÍ usa las subpartes de INP inicialmente para identificar si el retraso ya está ejecutando JavaScript (retraso de entrada), los controladores de eventos de JavaScript para la interacción (duración del procesamiento) o la renderización posterior (retraso de presentación).
  • SÍ intenta identificar el JavaScript de bloqueo más grande como detalle adicional, en particular para el retraso de entrada y la duración del procesamiento.
  • SÍ distingue entre el nuevo cálculo de estilo (styleDuration, forcedStyleDuration) y el diseño (layoutDuration, forcedLayoutDuration) cuando diagnostiques una duración de procesamiento alta o un retraso en la presentación: los tiempos de estilo altos indican selectores CSS costosos o invalidaciones amplias, mientras que los tiempos de diseño altos indican cuellos de botella en la geometría del DOM o un diseño síncrono excesivo.
  • SÍ prefiere la API de Long Animation Frames para proporcionar este detalle adicional en lugar de alternativas como la API de JS Self-Profiling, que genera una mayor sobrecarga de tiempo de ejecución.
  • SÍ usa la biblioteca web-vitals si no hay otra solución de RUM implementada. Puede identificar la interacción de INP y, además, incluye información sobre las partes secundarias y las secuencias de comandos que se ejecutaron durante la interacción (con la API de Long Animation Frames).
  • SÍ envía la información requerida a un servicio de estadísticas en lugar de solo registrarla de forma local.

Compatibilidad con navegadores y estrategias de resguardo

La API de Event Timing está disponible en la mayoría de los navegadores actualizados y es necesaria para calcular la INP y sus partes secundarias. En los navegadores que no admiten esta API, no se puede medir la INP.

La API de Long Animation Frames proporciona detalles adicionales opcionales. Se puede usar de forma segura sin resguardos. En la mayoría de los casos, las oportunidades de rendimiento que identifica también se aplicarán a otros navegadores.

Si tu objetivo de Baseline admite la API de Long Animation Frames (long-animation-frames), pero no admite propiedades de duración de estilo y diseño independientes (styleDuration y layoutDuration en PerformanceLongAnimationFrameTiming, o forcedStyleDuration y forcedLayoutDuration en PerformanceScriptTiming), recurre a los tiempos de estilo y diseño combinados:

  • Usa script.forcedStyleAndLayoutDuration en PerformanceScriptTiming para el trabajo de diseño y estilo forzado síncrono dentro de las secuencias de comandos.
  • Usa metric.attribution.totalStyleAndLayoutDuration en web-vitals/attribution (o calcula (entry.paintTime || entry.startTime + entry.duration) - entry.styleAndLayoutStart en cada entrada de PerformanceLongAnimationFrameTiming) para el trabajo combinado de estilo y diseño.