Cómo optimizar el retraso de entrada

Descubre qué es la demora de entrada y aprende técnicas para reducirla y lograr una mayor interactividad.

Las interacciones en la Web son complejas, ya que se produce todo tipo de actividad en el navegador para impulsarlas. Sin embargo, lo que tienen en común es que incurren en cierta demora de entrada antes de que comiencen a ejecutarse sus devoluciones de llamada de eventos. En esta guía, aprenderás qué es la demora de entrada y qué puedes hacer para minimizarla y que las interacciones de tu sitio web se ejecuten más rápido.

¿Qué es el retraso de entrada?

El retraso de entrada es el período que comienza cuando el usuario interactúa por primera vez con una página (por ejemplo, cuando presiona una pantalla, hace clic con el mouse o presiona una tecla) y finaliza cuando comienzan a ejecutarse las devoluciones de llamada de eventos para la interacción. Cada interacción comienza con una cierta cantidad de retraso de entrada.

Es una visualización simplificada del retraso de entrada. A la izquierda, hay un dibujo lineal de un cursor del mouse con una ráfaga detrás, lo que indica el inicio de una interacción. A la derecha, se muestra un dibujo lineal de una rueda dentada, que indica cuándo comienzan a ejecutarse los controladores de eventos para una interacción. El espacio entre ambos se indica como el retraso de entrada con una llave.
Los mecanismos detrás del retraso de entrada. Cuando el sistema operativo recibe una entrada, esta debe pasarse al navegador antes de que comience la interacción. Esto lleva una cierta cantidad de tiempo y puede aumentar con el trabajo existente del subproceso principal.

Una parte del retraso de entrada es inevitable: el sistema operativo siempre tarda un tiempo en reconocer un evento de entrada y pasarlo al navegador. Sin embargo, esa parte de la demora de entrada a menudo ni siquiera se nota, y hay otras cosas que suceden en la página que pueden hacer que las demoras de entrada sean lo suficientemente largas como para causar problemas.

Cómo pensar en el retraso de entrada

En general, te conviene mantener cada parte de una interacción lo más breve posible para que tu sitio web tenga la mejor oportunidad de cumplir con el umbral de "bueno" de la métrica de Interaction to Next Paint (INP), independientemente del dispositivo del usuario. Mantener bajo control el retraso de entrada es solo una parte del cumplimiento de ese umbral.

Por lo tanto, querrás intentar lograr el menor retraso de entrada posible para cumplir con el umbral de "bueno" del INP. Sin embargo, debes tener en cuenta que no puedes esperar eliminar las demoras de entrada por completo. Siempre y cuando evites el trabajo excesivo del subproceso principal mientras los usuarios intentan interactuar con tu página, la demora de entrada debería ser lo suficientemente baja como para evitar problemas.

Cómo minimizar la demora de entrada

Como se mencionó anteriormente, es inevitable que haya cierto retraso en la entrada, pero, por otro lado, cierto retraso en la entrada es evitable. A continuación, se incluyen algunos aspectos que debes tener en cuenta si tienes problemas con las demoras de entrada prolongadas.

Evita los temporizadores recurrentes que inician un trabajo excesivo en el subproceso principal

En JavaScript, hay dos funciones de temporizador que se usan con frecuencia y que pueden contribuir a la demora de entrada: setTimeout y setInterval. La diferencia entre ambos es que setTimeout programa una devolución de llamada para que se ejecute después de un tiempo especificado. Por otro lado, setInterval programa una devolución de llamada para que se ejecute cada n milisegundos de forma perpetua o hasta que se detenga el temporizador con clearInterval.

setTimeout no es problemático en sí mismo; de hecho, puede ser útil para evitar tareas largas. Sin embargo, depende de cuándo se produce el tiempo de espera y de si el usuario intenta interactuar con la página cuando se ejecuta la devolución de llamada de tiempo de espera.

Además, setTimeout se puede ejecutar en un bucle o de forma recursiva, en cuyo caso actúa más como setInterval, aunque es preferible no programar la siguiente iteración hasta que se complete la anterior. Si bien esto significa que el bucle cederá el control al subproceso principal cada vez que se llame a setTimeout, debes asegurarte de que su devolución de llamada no termine realizando un trabajo excesivo.

setInterval ejecuta una devolución de llamada en un intervalo y, por lo tanto, es mucho más probable que interfiera en las interacciones. Esto se debe a que, a diferencia de una sola instancia de una llamada a setTimeout, que es una devolución de llamada única que puede interferir en una interacción del usuario, la naturaleza recurrente de setInterval hace que sea mucho más probable que interfiera en una interacción, lo que aumenta la demora de entrada de la interacción.

Captura de pantalla del generador de perfiles de rendimiento en las Herramientas para desarrolladores de Chrome que muestra la demora de entrada. Una tarea activada por una función de temporizador ocurre justo antes de que un usuario inicie una interacción de clic. Sin embargo, el temporizador extiende la demora de entrada, lo que hace que las devoluciones de llamadas de eventos de la interacción se ejecuten más tarde de lo que lo harían de otra manera.
Un temporizador registrado por una llamada setInterval anterior que contribuye a la demora de entrada, como se muestra en el panel de rendimiento de las Herramientas para desarrolladores de Chrome. La demora de entrada agregada hace que las devoluciones de llamada de eventos para la interacción se ejecuten más tarde de lo que podrían hacerlo.

Si los temporizadores se ejecutan en el código propio, tienes control sobre ellos. Evalúa si los necesitas o haz todo lo posible para reducir el trabajo en ellos. Sin embargo, los temporizadores en secuencias de comandos de terceros son otra historia. A menudo, no tienes control sobre lo que hace un código externo, y solucionar los problemas de rendimiento en el código externo suele implicar trabajar con las partes interesadas para determinar si un código externo determinado es necesario y, si es así, establecer contacto con un proveedor de códigos externos para determinar qué se puede hacer para solucionar los problemas de rendimiento que puedan causar en tu sitio web.

Evita las tareas largas

Una forma de mitigar las demoras prolongadas en la entrada es evitar las tareas largas. Cuando tienes un exceso de trabajo en el subproceso principal que lo bloquea durante las interacciones, eso se sumará a la demora de entrada antes de que las tareas largas tengan la oportunidad de finalizar.

Es una visualización de cuánto tiempo las tareas extienden la demora de entrada. En la parte superior, se produce una interacción poco después de que se ejecuta una sola tarea larga, lo que provoca una demora significativa en la entrada que hace que las devoluciones de llamada de eventos se ejecuten mucho más tarde de lo que deberían. En la parte inferior, se produce una interacción aproximadamente al mismo tiempo, pero la tarea larga se divide en varias más pequeñas a través de la generación, lo que permite que las devoluciones de llamada de eventos de la interacción se ejecuten mucho antes.
Visualización de lo que sucede con las interacciones cuando las tareas son demasiado largas y el navegador no puede responder con la suficiente rapidez a las interacciones, en comparación con cuando las tareas más largas se dividen en tareas más pequeñas.

Además de minimizar la cantidad de trabajo que realizas en una tarea (y debes siempre esforzarte por realizar la menor cantidad de trabajo posible en el subproceso principal), puedes mejorar la capacidad de respuesta a la entrada del usuario dividiendo las tareas largas.

Ten en cuenta la superposición de interacciones

Una parte particularmente difícil de optimizar el INP puede ser si tienes interacciones que se superponen. La superposición de interacciones significa que, después de interactuar con un elemento, realizas otra interacción con la página antes de que la interacción inicial haya tenido la oportunidad de renderizar el siguiente fotograma.

Representación de cuándo las tareas pueden superponerse para producir retrasos de entrada prolongados. En esta representación, una interacción de clic se superpone con una interacción de presión de tecla para aumentar la demora de entrada de la interacción de presión de tecla.
Visualización de dos interacciones simultáneas en el generador de perfiles de rendimiento de las Herramientas para desarrolladores de Chrome. El trabajo de renderización en la interacción de clic inicial provoca un retraso de entrada para la interacción posterior del teclado.

Las fuentes de superposición de interacciones pueden ser tan simples como que los usuarios realicen muchas interacciones en un período corto. Esto puede ocurrir cuando los usuarios escriben en campos de formulario, en los que pueden producirse muchas interacciones del teclado en un período muy corto. Si el trabajo en un evento clave es especialmente costoso, como en el caso común de los campos de autocompletar en los que se realizan solicitudes de red a un backend, tienes algunas opciones:

  • Considera reducir el rebote de las entradas para limitar la cantidad de veces que se ejecuta una devolución de llamada de evento en un período determinado.
  • Usa AbortController para cancelar las solicitudes fetch salientes, de modo que el subproceso principal no se congestione controlando las devoluciones de llamada fetch. Nota: La propiedad signal de una instancia de AbortController también se puede usar para abortar eventos.

Otra fuente de aumento en el retraso de entrada debido a interacciones superpuestas pueden ser las animaciones costosas. En particular, las animaciones en JavaScript pueden activar muchas llamadas de requestAnimationFrame, lo que puede interferir en las interacciones del usuario. Para evitar esto, usa animaciones CSS siempre que sea posible para evitar poner en cola fotogramas de animación potencialmente costosos, pero, si lo haces, asegúrate de evitar las animaciones no compuestas para que las animaciones se ejecuten principalmente en los subprocesos de la GPU y del compositor, y no en el subproceso principal.

Conclusión

Si bien los retrasos en la entrada pueden no representar la mayor parte del tiempo que tardan en ejecutarse tus interacciones, es importante comprender que cada parte de una interacción ocupa una cantidad de tiempo que puedes reducir. Si observas un retraso de entrada prolongado, tienes oportunidades para reducirlo. Evitar las devoluciones de llamada del temporizador recurrentes, dividir las tareas largas y tener en cuenta la posible superposición de interacciones puede ayudarte a reducir la demora de entrada, lo que generará una interactividad más rápida para los usuarios de tu sitio web.

Imagen de héroe de Unsplash, de Erik Mclean.