Core Web Vitals

Cómo mejorar Interaction to Next Paint: diagnosticar los retrasos de entrada, procesamiento y renderizado

Un controlador rápido no basta si otra tarea impide que empiece o el navegador no puede mostrar su resultado.

Una onda de clic sobre tres símbolos conectados representa el retraso de entrada, el procesamiento y la presentación.

Para mejorar Interaction to Next Paint, reproduce una interacción lenta y averigua si el retraso ocurre antes de sus controladores, dentro de ellos o antes de mostrar el siguiente fotograma. Elimina trabajo innecesario, divide el restante cuando sea correcto hacerlo y reduce el renderizado costoso. Confirma el resultado con grabaciones interactivas y mediciones reales, no solo con una mejor puntuación de carga.

INP es bueno con 200 milisegundos o menos en el percentil 75. Describe la respuesta durante una visita: la acción que lo determina puede suceder mucho después de que la página parezca lista. Un filtro de productos o el menú puede ser el problema aunque la carga sea rápida.

Entiende qué mide INP y qué deja fuera

INP evalúa clics, toques e interacciones de teclado válidos. Considera el retraso hasta el siguiente renderizado tras el trabajo pertinente. No es solo la ejecución del controlador ni un cronómetro de todo el proceso comercial posterior al clic.

Una búsqueda, por ejemplo, puede mostrar inmediatamente un estado de carga mientras una solicitud asíncrona obtiene resultados. Ese aviso mejora la respuesta percibida, pero no acelera la red. Mide también el tiempo hasta completar la tarea si el objetivo del visitante depende del resultado posterior.

La métrica suele reflejar la interacción más lenta de la visita, con una tolerancia para valores extremos cuando hay muchas interacciones. Una visita sin interacción válida no tiene medición INP. No sustituyas esa ausencia por cero ni la interpretes como una respuesta instantánea.

INP sustituyó a First Input Delay como Core Web Vital en marzo de 2024. FID solo cubría el retraso inicial de la primera interacción válida, no la respuesta completa durante la visita. Las recomendaciones centradas en FID pueden pasar por alto una interacción posterior lenta o trabajo de presentación costoso.

La guía de Core Web Vitals para principiantes explica umbrales y percentiles. Distingue esos resultados de población de una interacción que reproduces deliberadamente en desarrollo.

Divide la latencia en tres fases

Cada fase sugiere una investigación distinta. La guía de optimización de INP de Google conecta así la métrica con el trabajo del hilo principal.

Fase Qué ocurre Qué inspeccionar
Retraso de entrada La entrada espera antes de iniciar controladores Tareas largas previas, temporizadores y scripts
Duración del procesamiento Se ejecutan los controladores Cálculo, trabajo síncrono y controladores repetidos
Retraso de presentación El navegador prepara y muestra el siguiente fotograma Estilos, diseño, pintura y grandes cambios DOM

Un controlador corto puede sentirse lento porque otro script bloquea su inicio. También puede terminar pronto y desencadenar un cálculo de diseño costoso. Medir solo la duración de una función omite ambos casos.

Empieza por la fase más larga de la traza problemática. Después revisa otra vez toda la interacción. Trasladar trabajo entre fases quizá no reduzca la latencia total; una actualización más pequeña puede mejorar varias a la vez.

Graba la interacción en un estado representativo

Usa Performance en Chrome DevTools para registrar la acción. Inicia la grabación, reproduce la interacción, detén y examina la secuencia. Incluye el estado relevante: menú abierto, carrito con productos, lista desplegada o contenido acumulado tras desplazarte.

Una página recién abierta y vacía puede no reproducir un problema que aparece después de varias actualizaciones. En cambio, extensiones ajenas pueden introducir trabajo que tus visitantes no reciben. Controla el entorno conservando las partes del recorrido real que afectan al resultado.

Cuando puedas, utiliza hardware representativo del público. Limitar CPU ayuda a detectar sensibilidad, pero es una simulación y debe registrarse así. No presentes una traza local limitada como comportamiento medido en un teléfono concreto si no lo probaste.

Guarda el objetivo de la interacción, las condiciones y la pila de llamadas pertinente. Un informe útil identifica el control lento y el trabajo que ocupa ese intervalo. Una captura de un resultado agregado rojo obliga a la siguiente persona a repetir la investigación.

Añade atribución donde terminan los informes agregados

CrUX y Search Console pueden detectar un problema de población sin identificar el componente o despliegue responsable. Tu instrumentación puede relacionar interacciones lentas con el contexto de aplicación, según privacidad y soporte del navegador.

Este módulo usa la versión de atribución de web-vitals con un paquete compatible instalado. Registra las fases sin enviar detalles de interacción a un servidor.

js
import { onINP } from 'web-vitals/attribution';

onINP(({ value, attribution }) => {
  console.table({
    inp: value,
    inputDelay: attribution.inputDelay,
    processingDuration: attribution.processingDuration,
    presentationDelay: attribution.presentationDelay
  });
});

Comprueba la API con la versión instalada. Un recolector de producción necesita agregación, deduplicación y una política sobre el contexto registrado. No recojas texto escrito, identificadores de cuenta o URL completas con parámetros privados solo porque resulte fácil adjuntarlos.

Trata la atribución como una pista para reproducir. Su cobertura puede diferir de CrUX y una métrica agregada puede ocultar varios tipos de interacción lenta. Agrupa por plantilla o componente cuando proceda, sin asumir una causa única para todas las muestras.

Elimina el trabajo que impide iniciar la entrada

El hilo principal no puede ejecutar un controlador de entrada mientras otra tarea lo ocupa. Las tareas de más de 50 milisegundos se clasifican como largas, aunque las más cortas también pueden contribuir cuando se acumulan planificación y renderizado.

Inspecciona el intervalo inmediatamente anterior a los controladores. Busca inicialización, temporizadores repetidos, analítica, hidratación y widgets externos. El control puede ser inocente: un menú ligero puede tardar porque otro trabajo monopolizó el hilo.

Elimina funciones sin uso e inicializaciones duplicadas antes de diseñar una planificación compleja. Dividir código evita cargar y evaluar funciones que una ruta no necesita. Aplazar un script cambia cuándo se ejecuta, pero no elimina su coste.

Para código costoso necesario, estudia tareas más pequeñas o ejecución fuera del hilo principal. La guía de ejecución de JavaScript desarrolla estas opciones. El objetivo es reducir competencia alrededor de interacciones reales, no únicamente de la carga inicial.

Cede el control entre partes independientes

Dividir una función en varias pequeñas no divide automáticamente la tarea del navegador. Invocarlas seguidas dentro del mismo controlador mantiene ocupado el hilo hasta terminar.

scheduler.yield() reanuda el trabajo en una tarea posterior. Como el soporte varía, conviene detectar la función y ofrecer alternativa. Un temporizador también crea otra tarea, pero no tiene el mismo comportamiento de prioridad de continuación.

Este ejemplo completo procesa una colección local en fragmentos ilustrativos. El tamaño elegido demuestra la técnica, no fija un presupuesto universal de rendimiento.

html
<button id="process" type="button">Process example data</button>
<p id="progress" role="status">Ready</p>
<script type="module">
  const button = document.querySelector('#process');
  const progress = document.querySelector('#progress');
  const values = Array.from({ length: 10000 }, (_, index) => index);

  async function yieldToBrowser() {
    if (globalThis.scheduler?.yield) {
      await globalThis.scheduler.yield();
    } else {
      await new Promise(resolve => setTimeout(resolve, 0));
    }
  }

  button.addEventListener('click', async () => {
    button.disabled = true;
    progress.textContent = 'Processing';
    try {
      let total = 0;
      for (let start = 0; start < values.length; start += 250) {
        await yieldToBrowser();
        const end = Math.min(start + 250, values.length);
        for (let index = start; index < end; index++) {
          total += values[index];
        }
      }
      progress.textContent = `Total: ${total}`;
    } finally {
      button.disabled = false;
    }
  });
</script>

Ceder el control ofrece al navegador una oportunidad de hacer otras cosas; no garantiza que un fotograma determinado aparezca en un instante concreto. Mide la operación real en dispositivos representativos y ajusta el trabajo por fragmento.

No cedas a mitad de una actualización de estado que deba ser atómica. Puede ejecutarse otro código antes de continuar y cambiar el estado compartido. Conserva la corrección, gestiona cancelación cuando sea necesaria y haz segura la activación repetida. Aplicar una acción dos veces no es una mejora.

Usa requestIdleCallback solo para trabajo opcional de fondo, con detección y alternativa apropiadas. Su callback puede esperar mientras el navegador está ocupado: no sustituye al aviso inmediato ni a trabajo necesario para completar la operación. Un tiempo límite acota la espera, pero entonces la ejecución deja de restringirse a períodos inactivos.

Mantén pequeña y útil la respuesta inmediata

Revisa qué trabajo no debe preceder al aviso visual. Actualizar una selección puede ser esencial. Recalcular un informe ajeno, cargar un widget oculto o enviar analítica secundaria puede no serlo.

No sustituyas la respuesta real por un éxito engañoso. Si una operación puede fallar, indica que está en curso en lugar de darla por terminada. Mantén manejo de errores y anuncios de accesibilidad para usuarios de teclado y tecnologías de apoyo.

Los workers ayudan con cálculos adecuados, como analizar o transformar grandes colecciones. No manipulan directamente el DOM y comunicarse con ellos cuesta. Trasladar una operación mínima puede añadir complejidad sin beneficio; trasladar la operación costosa correcta libera el hilo para entrada y renderizado.

Comprueba también la frecuencia de ejecución. Listeners duplicados, efectos repetidos y propagación innecesaria de estado multiplican trabajo moderado. Elimina la duplicación en lugar de ocultarla con una demora.

En entradas repetidas, como sugerencias de búsqueda, debounce evita procesar cada valor intermedio. Mantén fluida la escritura, elige el retraso según la tarea y cancela o ignora resultados asíncronos antiguos. No apliques debounce a todos los controles ni retrases un aviso visible por un temporizador arbitrario.

Reduce el renderizado posterior al controlador

La presentación puede dominar cuando una interacción modifica gran parte de la página. Examina recálculo de estilos, disposición y pintura después del controlador. Una función corta que inserta miles de nodos puede generar mucho trabajo del navegador.

Actualiza la región pertinente más pequeña. Considera paginación o virtualización cuidadosamente implementada para colecciones grandes, conservando navegación, foco y contenido accesible. Un DOM inicial menor solo ayuda si la interacción posterior no recrea todo el problema de golpe.

Evita alternar repetidamente lecturas de diseño y escrituras dentro de un bucle. Leer geometría actual después de cambiar estilos puede forzar un cálculo síncrono. Agrupa mediciones cuando sea posible, aplica después los cambios y comprueba en la traza si disminuyó el diseño forzado.

No uses un número concreto de nodos DOM como umbral universal. La complejidad, las dependencias de estilos y la región actualizada afectan al coste. La prueba relevante es el trabajo de renderizado provocado, no estar por debajo de una cifra memorizada.

Audita terceros durante la misma acción

Gestores de etiquetas, chat, experimentos y publicidad pueden ejecutarse durante interacciones aunque sus descargas hayan terminado antes. Una auditoría solo de red no detecta ese coste.

En una prueba controlada, bloquea temporalmente un recurso sospechoso o desactiva una integración concreta y repite. Comprueba que la página siga funcionando y que el cambio aísle la causa. Una dependencia ausente que rompe la función puede generar una traza engañosamente rápida.

Asigna responsable y motivo a cada integración en ese punto del recorrido. Carga un elemento opcional a demanda cuando beneficie al usuario, pero recuerda que su primera interacción puede incluir inicialización. Una fachada no debería limitarse a trasladar todo el coste al clic que la activa.

Valida más que una traza favorable

Una ejecución estándar de navegación Lighthouse mide carga y presenta TBT como indicador de bloqueo. No genera las interacciones de visitantes necesarias para INP de campo. No conviertas TBT en INP ni uses una puntuación mejor como prueba de que el filtro lento quedó arreglado.

Repite la interacción real en condiciones comparables. Revisa fases, respuesta visible, resultado final y errores. Después del despliegue, monitoriza datos reales por dispositivo y plantilla pertinentes.

Usa la lista de comprobación de rendimiento para registrar cambio y condiciones de verificación, y las guías de Core Web Vitals para problemas de carga o estabilidad restantes. Conserva el escenario como prueba de regresión para que futuros cambios de scripts o diseño no reintroduzcan el retraso.

Guías relacionadas