Tiempo de procesamiento de INP: causas, optimización y ejemplos de código
Aprenda a encontrar y mejorar los problemas de INP causados por el tiempo de procesamiento

Problemas de Interaction to Next Paint (INP) causados por el tiempo de procesamiento
Esta página forma parte de nuestra serie sobre Interaction to Next Paint (INP). El INP mide el tiempo total desde una interacción del usuario hasta la siguiente actualización visual. El tiempo de procesamiento es la segunda de las tres fases que componen el INP, precedida por el retraso de entrada (input delay) y seguida por el retraso de presentación (presentation delay). Si es nuevo en el INP, lea primero nuestra guía sobre cómo identificar y solucionar problemas de INP.
En resumen: El Interaction to Next Paint (INP) mide cuánto tiempo tarda un usuario en ver un cambio visual en una página después de interactuar con ella. Este INP se puede dividir en 3 componentes: "retraso de entrada" (input delay), "tiempo de procesamiento" (processing time) y "retraso de presentación" (presentation delay).
El tiempo de procesamiento es un factor importante en el INP total, representando aproximadamente el 40% del retraso en promedio. Optimizar sus controladores de eventos es la forma más directa de reducir el tiempo de procesamiento y mejorar su puntuación de INP.
CONSEJO DE INP: el tiempo de procesamiento se puede optimizar ejecutando inmediatamente el código importante que precede a la actualización del diseño y programando el resto del código para que se ejecute después.
Table of Contents!
- Problemas de Interaction to Next Paint (INP) causados por el tiempo de procesamiento
- ¿Qué es el tiempo de procesamiento?
- El tiempo de procesamiento y el INP
- ¿Qué causa un alto tiempo de procesamiento?
- Minimizar el tiempo de procesamiento
- Dividir los controladores de eventos con setTimeout(0)
- Uso de requestAnimationFrame para actualizaciones visuales
- Cómo priorizar el código crítico
- Programación detallada con scheduler.postTask()
- Implicaciones prácticas
- Explore las otras fases de INP
¿Qué es el tiempo de procesamiento?

El Interaction to Next Paint (INP) se puede dividir en 3 subpartes: "Retraso de entrada", "Tiempo de procesamiento" y "Retraso de presentación".
El tiempo de procesamiento se refiere al tiempo que tarda el navegador en ejecutar todos los callbacks de eventos asociados después de que un usuario interactúa con una página web (por ejemplo, al hacer clic en un botón o presionar una tecla). Aunque siempre hay algo de tiempo de procesamiento, los problemas de INP ocurren cuando los callbacks de eventos consumen demasiado tiempo de procesamiento.
En pocas palabras: el tiempo de procesamiento es la duración del "trabajo" que ocurre en respuesta a su interacción. Cuando hace clic en un botón de búsqueda, el tiempo de procesamiento incluye todo, desde la validación de su consulta, la preparación de la solicitud de la API, la actualización del estado local, la activación de eventos de análisis y cualquier otro código adjunto a ese evento de clic. Cada línea de JavaScript en esos controladores de eventos contribuye al tiempo de procesamiento.
El tiempo de procesamiento y el INP
El tiempo de procesamiento puede ser lo primero que le venga a la mente cuando piensa en optimizar el Interaction to Next Paint. Es el "trabajo que debe hacerse" antes de que el navegador pueda actualizar el diseño.
Muchos desarrolladores piensan en mejorar el INP en términos de optimizar las funciones de callback (optimizando el tiempo de procesamiento), y tienen razón. Pero en términos de importancia, el tiempo de procesamiento ni siquiera es la parte más importante a mejorar. Aun así, en promedio, representa aproximadamente el 40% del tiempo total de INP.

En CoreDash recopilamos millones de puntos de datos de Core Web Vitals cada hora. Según esos datos, el tiempo de procesamiento representa el 40% del Interaction to Next Paint. Un 40% es mucho, pero optimizar solo el tiempo de procesamiento no solucionará los problemas de INP. También debe prestar atención al retraso de entrada (18%) y al retraso de presentación (42%).
Ejemplo de tiempo de procesamiento: Cuando un usuario hace clic en un botón para enviar un formulario, el código que valida los datos del formulario, los envía al servidor y maneja la respuesta contribuye al tiempo de procesamiento. Cuanto más tarden estas operaciones, mayor será el tiempo de procesamiento y, potencialmente, peor será la puntuación de INP.
¿Qué causa un alto tiempo de procesamiento?
El alto tiempo de procesamiento tiene cuatro causas comunes: código innecesario, código no optimizado, callbacks agrupados y layout thrashing.

- Código innecesario. El código antiguo y sin usar o el código sin relevancia inmediata para la interacción del usuario puede prolongar el tiempo de ejecución del callback. Esto incluye llamadas de análisis, registro (logging) y sincronización de estado que no necesitan completarse antes del siguiente paint.
- Código no optimizado. El código ineficiente (generalmente bucles o búsquedas ineficientes en el DOM) puede hacer que los callbacks de eventos se ejecuten más lentamente de lo necesario. Un ejemplo común es consultar el DOM dentro de un bucle con
document.querySelectorAll()en lugar de almacenar en caché el resultado antes del bucle. - Callbacks agrupados. Múltiples callbacks de eventos programados cerca unos de otros crean una cola. Si un callback desencadenado por la interacción del usuario se atasca en esta cola, la respuesta parece retrasada. Por ejemplo, un controlador de
pointerdown, un controlador demousedowny un controlador declickpueden dispararse secuencialmente para un solo clic. - Layout thrashing. Las manipulaciones frecuentes del DOM que desencadenan recálculos de diseño pueden sobrecargar el navegador y provocar regresiones en el rendimiento. Esto ocurre cuando su código alterna entre leer y escribir propiedades de diseño dentro de un bucle, forzando al navegador a recalcular el diseño varias veces.
Minimizar el tiempo de procesamiento

La estrategia es doble: optimizar el código existente (eliminar el código innecesario y optimizar el código actual) y distinguir entre el código que debe ejecutarse antes y después de la actualización del diseño. El código que es crítico para la actualización del diseño debe ejecutarse primero, y todo el demás código puede ejecutarse después de la actualización del diseño.
- Eliminar código no utilizado. Aunque eliminar código no utilizado puede parecer obvio, en la mayoría de los sitios hay al menos algo de código antiguo sin usar que simplemente se ejecuta sin aportar realmente nada a la página ni a la UX. Lo primero que hay que hacer es asegurarse de que no se esté ejecutando código que no sea necesario. Esto se puede hacer mediante tree shaking, división de código (code splitting), inspeccionando la cobertura de su código en Chrome y usando un buen IDE que le indique el código no utilizado. (Consejo profesional: analice también críticamente los recursos cargados por su Google Tag Manager). Para obtener más estrategias, consulte nuestra guía sobre 14 métodos para diferir JavaScript.
- Minimizar el tiempo de ejecución de los callbacks. Utilice un generador de perfiles (profiler) de JavaScript para identificar cuellos de botella en su código y apunte a esas áreas para su optimización. Considere técnicas como la memoización, el precálculo y el almacenamiento en caché para evitar cálculos redundantes. (Consejo: puede usar el panel de rendimiento de Chrome para encontrar scripts con tiempos de ejecución prolongados).
- Priorizar el código crítico y programar el resto del código. Cuando el código del callback se haya optimizado, divida el código en aquel que debe ejecutarse inmediatamente y el código que se puede diferir. Eche un vistazo a este ejemplo de la vida real:

En este ejemplo, los callbacks de eventos de Google Tag Manager y Facebook se ejecutan antes del código (React) que precede a la actualización del diseño. La solución es programar los callbacks de GTM y Facebook para que se ejecuten cuando el navegador esté inactivo (idle). - Evitar el layout thrashing o reflow. El layout thrashing ocurre cuando las actualizaciones de estilo y las lecturas de estilo se mezclan en un bucle, lo que hace que el navegador recalcule el diseño en numerosas ocasiones. Para evitar el layout thrashing, realice todos los cambios de estilo (los "sets") antes de solicitar los valores de estilo (los "gets"). Este enfoque minimiza la frecuencia de las actualizaciones de diseño, lo que lleva a una página más rápida. Por ejemplo, en un bucle que establece el ancho de cada párrafo para que coincida con el ancho de un elemento, lea el ancho del elemento una vez antes del bucle y use ese valor para actualizar los anchos de los párrafos dentro del bucle.
Dividir los controladores de eventos con setTimeout(0)
Cuando no puede eliminar o diferir código de un controlador de eventos, la siguiente mejor opción es dividir el controlador en fragmentos más pequeños. El patrón setTimeout(callback, 0) le permite dividir el trabajo en múltiples tareas, dándole al navegador la oportunidad de manejar la actualización del diseño entre ellas. Aquí hay un ejemplo práctico:
// Antes: un controlador de eventos largo bloquea el siguiente paint
button.addEventListener('click', () => {
updateUI(); // Crítico: debe ejecutarse antes del paint
validateForm(); // Importante pero puede esperar
sendAnalytics(); // No crítico
syncLocalStorage(); // No crítico
});
// Después: se divide en trabajo crítico y diferido
button.addEventListener('click', () => {
updateUI(); // Crítico: se ejecuta inmediatamente antes del paint
setTimeout(() => {
validateForm();
}, 0);
setTimeout(() => {
sendAnalytics();
syncLocalStorage();
}, 0);
});
La desventaja de setTimeout(0) es que coloca la continuación al final de la cola de tareas. Si ya hay otras tareas en cola, es posible que el código diferido no se ejecute de inmediato. Para un comportamiento más predecible, use scheduler.yield() en su lugar (consulte la sección a continuación). Para patrones que se enfocan específicamente en el manejo de scroll con JavaScript, consulte nuestra guía dedicada.
Uso de requestAnimationFrame para actualizaciones visuales
Cuando su controlador de eventos necesita desencadenar una actualización visual, requestAnimationFrame() asegura que su código se ejecute en el momento óptimo: justo antes de que el navegador realice su siguiente repintado (repaint). Esto es especialmente útil cuando necesita agrupar en lotes (batch) las lecturas y escrituras del DOM para evitar el layout thrashing.
// Use requestAnimationFrame para agrupar actualizaciones visuales
button.addEventListener('click', () => {
// Leer propiedades de diseño primero (fuera de rAF)
const containerWidth = container.offsetWidth;
requestAnimationFrame(() => {
// Escribir propiedades de diseño dentro de rAF
items.forEach(item => {
item.style.width = containerWidth + 'px';
});
});
// Programar trabajo no visual para el tiempo de inactividad (idle time)
requestIdleCallback(() => {
trackButtonClick();
updateSessionState();
});
});
Este patrón separa las lecturas del DOM de las escrituras del DOM, evitando el diseño sincrónico forzado (forced synchronous layout). La actualización visual se ejecuta en el momento ideal en el pipeline de renderizado del navegador, y el trabajo no visual se ejecuta durante el tiempo de inactividad.
Cómo priorizar el código crítico
"Priorizar el código crítico y programar el resto del código" suena abstracto, así que esto es lo que parece en la práctica. Podemos priorizar el código crítico usando requestIdleCallback() y realizando un yielding al hilo principal (main thread).
Usamos requestIdleCallback para tareas menos importantes que no necesitan ejecutarse de inmediato. Aquí hay un ejemplo del antes y el después de programar un evento de GTM:
/* antes: ejecutar código inmediatamente */
gtag('event', '<event_name>', {
'event_category': '<event_category>',
});
/* después: ejecutar el mismo código durante la inactividad del navegador */
requestIdleCallback(() => {
gtag('event', '<event_name>', {
'event_category': '<event_category>',
});
}, { timeout: 1000 });
La desventaja de requestIdleCallback es que el código podría no ejecutarse tan pronto como le gustaría. En ese caso, puede hacer un "yielding al hilo principal" después de que se haya ejecutado el código más importante, dándole al navegador un momento para realizar la actualización del diseño. Aquí hay un ejemplo de cómo dividir tareas mediante el yielding al hilo principal:
async function yieldToMain() {
if ('scheduler' in window && 'yield' in window.scheduler) {
return await window.scheduler.yield();
}
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
async function handleClick() {
// Realice las actualizaciones de diseño más importantes aquí
await yieldToMain();
// Realice otras tareas que deban ejecutarse lo antes posible después de la actualización del diseño
}
Programación detallada con scheduler.postTask()
La función scheduler.postTask() proporciona una programación más detallada de las tareas mediante el establecimiento de prioridades, lo que ayuda al navegador a priorizar el trabajo para que las tareas de baja prioridad hagan un yielding al hilo principal. Verifique la tabla de compatibilidad del navegador antes de usar esta API en producción.
La función postTask() acepta tres configuraciones de prioridad: "background" para las tareas de menor prioridad, "user-visible" para tareas de prioridad media y "user-blocking" para tareas críticas que requieren alta prioridad.
Al asignar la prioridad correcta a cada parte del trabajo dentro de su controlador de eventos, puede asegurarse de que el navegador maneje las interacciones del usuario de manera receptiva mientras completa todas las tareas necesarias:
// Programar trabajo crítico de la UI con alta prioridad
scheduler.postTask(() => {
updateCartBadge();
showConfirmation();
}, { priority: 'user-blocking' });
// Programar la sincronización de datos con prioridad media
scheduler.postTask(() => {
syncCartWithServer();
}, { priority: 'user-visible' });
// Programar análisis con baja prioridad
scheduler.postTask(() => {
gtag('event', 'add_to_cart', { item: productId });
fbq('track', 'AddToCart');
}, { priority: 'background' });
Implicaciones prácticas
Así es como debe abordar la optimización del tiempo de procesamiento en WordPress y React/Next.js.
WordPress
WordPress ofrece un control limitado cuando se trata de scripts de terceros. Muchos scripts se agregan a través de plugins. La mayoría de las veces, esos scripts agregarán event listeners a la página que no hacen nada más que retrasar el Interaction to Next Paint (INP). Si su sitio de WordPress tiene problemas con el INP causados por un largo tiempo de procesamiento, siga estos pasos:
- Verifique la configuración del tema. Desmarque cualquier opción innecesaria como "scroll suave" o "menú animado". Configuraciones como estas tienden a causar problemas de INP.
- Verifique qué scripts son responsables del largo tiempo de procesamiento (consejo: use el panel de rendimiento de Chrome). Si esos scripts están relacionados con plugins, considere buscar otro plugin que haga aproximadamente lo mismo con menos JavaScript.
- A menudo hay scripts personalizados ejecutándose en la página. Revise esos scripts y asegúrese de que hagan yielding al hilo principal con frecuencia y envuelva los callbacks menos importantes en una función
requestIdleCallback. - Descargue los scripts no utilizados página por página (consejo: use
wp_deregister_script). Algunos plugins tienden a inyectar scripts en todas las páginas incluso cuando la funcionalidad no es necesaria. - Revise su Google Tag Manager y elimine las etiquetas no utilizadas o innecesarias.
- Use temas ligeros y limpios. Los temas multipropósito que "hacen de todo" tienden a tener más scripts y controladores de eventos más pesados.
- Evite los creadores de páginas (page builders) ya que a menudo dependen en gran medida de JavaScript para presentar páginas al usuario final.
React / Next.js
Los hooks y las características de concurrencia de React hacen posible reducir considerablemente el tiempo de procesamiento del INP. Aquí están las técnicas clave:
Priorizar la interacción del usuario con las características de concurrencia de React:
React 18 introdujo características de concurrencia que optimizan el renderizado para una experiencia de usuario más fluida, especialmente durante la entrada de datos (input).
useTransitionystartTransition: Marcan las actualizaciones no críticas para un renderizado posterior. Esto evita que grandes actualizaciones bloqueen la interacción del usuario. Por ejemplo, envuelva una actualización de resultados de búsqueda enstartTransitionpara que la escritura en el cuadro de búsqueda siga siendo receptiva.useDeferredValue: Divide su UI en secciones esenciales y menos críticas. React puede interrumpir el renderizado de las partes menos críticas para una experiencia más receptiva. Esto es ideal para renderizar listas filtradas o resultados de búsqueda.useOptimistic(React 19+): Muestra un estado optimista temporal mientras las operaciones asincrónicas (como las solicitudes de red) están en curso. Esto mantiene la UI receptiva incluso durante la obtención de datos (data fetching).
Suspense para la obtención de datos (React 18+)
Suspense en React 18 se puede utilizar para mejorar el INP al permitir que el navegador priorice las interacciones del usuario y optimice el renderizado. Mientras que React 16 introdujo Suspense para la división de código (code splitting), React 18 extiende esta funcionalidad para abarcar la obtención de datos (data fetching).
- Un componente fallback, como un indicador de carga, se muestra mientras se cargan los datos.
- Una vez que llegan los datos, React reanuda el renderizado del componente suspendido.
- Suspense, combinado con el renderizado interrumpible en Concurrent React, prioriza las interacciones del usuario. Si un usuario interactúa con un componente suspendido, React prioriza el renderizado de ese componente, manteniendo la capacidad de respuesta.
Estas características ayudan a React a priorizar las interacciones del usuario sobre el trabajo de renderizado en segundo plano.
Explore las otras fases de INP
El tiempo de procesamiento es solo una parte del Interaction to Next Paint. Para optimizar completamente sus puntuaciones de INP, también debe abordar las otras dos fases:
- Retraso de entrada (Input Delay): Minimice el tiempo de espera antes de que los controladores de eventos comiencen a ejecutarse. El retraso de entrada representa aproximadamente el 18% del tiempo total de INP.
- Retraso de presentación (Presentation Delay): Reduzca el trabajo de renderizado y pintura que representa aproximadamente el 42% del tiempo total de INP.
Para un flujo de trabajo de diagnóstico completo, consulte nuestra guía sobre cómo encontrar y solucionar problemas de INP, y regrese a la página principal de INP para obtener una descripción general completa.
Your Lighthouse score is not the full picture.
Lab tests run on fast hardware with a stable connection. I analyze what your actual visitors experience on real devices and real networks.
Analyze Field Data
