Cómo funciona el navegador web moderno (parte 4)

Mariko Kosaka

La entrada estará disponible en el compositor

Esta es la última de las 4 partes de la serie de blogs sobre Chrome. investigar cómo se encarga nuestro código para mostrar un sitio web. En la publicación anterior, analizamos el proceso de renderización y aprendimos sobre el compositor. En esta publicación, Observa cómo el compositor permite una interacción fluida cuando ingresa la entrada del usuario.

Eventos de entrada desde el punto de vista del navegador

Cuando escuches "eventos de entrada" Puede que solo se piense en escribir en el cuadro de texto o hacer clic con el mouse, pero, desde el punto de vista del navegador; entrada significa cualquier gesto del usuario. El desplazamiento de la rueda del mouse es una entrada y tocar o colocar el mouse sobre ella también es un evento de entrada.

Cuando se produce un gesto del usuario, como tocar en una pantalla, el proceso del navegador es el que recibe al principio. Sin embargo, el proceso del navegador solo sabe dónde ocurrió ese gesto, ya que el contenido de una pestaña se controla mediante el proceso del renderizador. El proceso del navegador envía el evento (como touchstart) y sus coordenadas al proceso del renderizador. El proceso del renderizador controla de forma adecuada buscando el destino del evento y ejecutando objetos de escucha de eventos adjuntos.

evento de entrada
Figura 1: Evento de entrada enrutado desde el proceso del navegador al proceso del renderizador
.

El compositor recibe eventos de entrada

. Figura 2: Ventana de visualización que se desplaza sobre las capas de página
.

En la publicación anterior, vimos cómo el compositor podía hacer avanzar el desplazamiento sin problemas al componer capas rasterizadas. Si no hay objetos de escucha de eventos de entrada adjuntos a la página, el subproceso del compositor crearás un nuevo marco compuesto completamente independiente del subproceso principal. Pero ¿qué pasa si algún evento objetos de escucha estaban adjuntos a la página? ¿Cómo determinaría el subproceso compositor si el evento necesita que se debe manejar?

Información sobre las regiones no desplazables rápido

Como ejecutar JavaScript es el trabajo del subproceso principal, cuando se compone una página, el subproceso compositor marca una región de la página que tiene controladores de eventos adjuntos como "Región no desplazable rápida". De teniendo esta información, el subproceso compositor puede asegurarse de enviar el evento de entrada al subproceso principal si el evento ocurre en esa región. Si el evento de entrada proviene fuera de esta región, el subproceso compositor continúa componendo un nuevo marco sin esperar al subproceso principal.

región limitada con desplazamiento rápido
Figura 3: Diagrama de la entrada descrita en la región desplazable no rápida
.

Ten cuidado cuando escribas controladores de eventos

Un patrón común de control de eventos en el desarrollo web es la delegación de eventos. Como el cuadro de eventos, Puedes adjuntar un controlador de eventos en el elemento superior y delegar tareas en función del destino del evento. Tú podrían haber visto o escrito un código como el que se muestra a continuación.

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault();
    }
});

Como solo necesitas escribir un controlador de eventos para todos los elementos, la ergonomía de este evento patrón de delegación son atractivos. Sin embargo, si observas este código desde el punto de , ahora toda la página se marca como una región no desplazable rápida. Esto significa que incluso si tus no le interesa la entrada de ciertas partes de la página, el subproceso del compositor comunicarse con el subproceso principal y esperar cada vez que entre un evento de entrada. Por lo tanto, el se anula la capacidad de desplazamiento suave del compositor.

Región no desplazable rápida de página completa
Figura 4: Diagrama de la entrada descrita en la región de desplazamiento no rápido que cubre toda una página
.

Para mitigar esto, puedes pasar opciones de passive: true en tu evento. objeto de escucha. Esto le indica al navegador que aún deseas escuchar el evento en el subproceso principal. pero el compositor puede crear también un nuevo fotograma.

document.body.addEventListener('touchstart', event => {
    if (event.target === area) {
        event.preventDefault()
    }
 }, {passive: true});

Verifica si el evento se puede cancelar

desplazamiento de página
Figura 5: Una página web con parte de la página fija en el desplazamiento horizontal
.

Imagina que tienes un cuadro en una página y quieres limitar la dirección de desplazamiento al desplazamiento horizontal únicamente.

El uso de la opción passive: true en el evento del puntero significa que el desplazamiento de la página puede ser fluido, pero es posible que el desplazamiento vertical haya comenzado cuando desees que preventDefault para limitar la dirección de desplazamiento. Puedes verificar esto con el método event.cancelable.

document.body.addEventListener('pointermove', event => {
    if (event.cancelable) {
        event.preventDefault(); // block the native scroll
        /*
        *  do what you want the application to do here
        */
    }
}, {passive: true});

Como alternativa, puedes usar una regla de CSS como touch-action para eliminar por completo el controlador de eventos.

#area {
  touch-action: pan-x;
}

Cómo encontrar el objetivo del evento

prueba de posicionamiento
Figura 6: Subproceso principal que observa los registros de pintura preguntando qué se dibujó en el punto x.y
.

Cuando el subproceso compositor envía un evento de entrada al subproceso principal, lo primero que se debe ejecutar es un hit. prueba para encontrar el objetivo del evento. La prueba de posicionamiento usa los datos de registros de pintura que se generaron en la renderización para averiguar qué hay debajo de las coordenadas de los puntos en los que ocurrió el evento.

Minimiza los envíos de eventos al subproceso principal

En la publicación anterior, discutimos cómo nuestra típica pantalla actualiza la pantalla 60 veces por segundo y y veremos cómo debemos seguir el ritmo para lograr una animación fluida. Para la entrada, una pantalla táctil típica El dispositivo entrega eventos táctiles entre 60 y 120 veces por segundo, y un mouse típico genera eventos 100 veces por segundo. por segundo. El evento de entrada tiene una fidelidad superior a la que puede actualizarse nuestra pantalla.

Si un evento continuo como touchmove se envió al subproceso principal 120 veces por segundo, entonces podría activar una cantidad excesiva de pruebas de posicionamiento y ejecución de JavaScript en comparación con la lentitud de la la pantalla puede actualizarse.

eventos sin filtrar
Figura 7: Eventos que sobrecargan el cronograma de fotogramas y causan el bloqueo de la página
.

Para minimizar las llamadas excesivas al subproceso principal, Chrome combina los eventos continuos (como wheel, mousewheel, mousemove, pointermove, touchmove ) y se demorará el envío hasta el justo antes del próximo requestAnimationFrame.

eventos fusionados
Figura 8: El mismo cronograma que antes, pero el evento se fusiona y se retrasa.
.

Cualquier evento discreto, como keydown, keyup, mouseup, mousedown, touchstart y touchend se envían de inmediato.

Cómo usar getCoalescedEvents para obtener eventos dentro del fotograma

En el caso de la mayoría de las aplicaciones web, los eventos combinados deberían ser suficientes para proporcionar una buena experiencia del usuario. Sin embargo, si compilas elementos como dibujar una aplicación y colocas una ruta de acceso basada en touchmove, es posible que pierdas un punto intermedio para dibujar una línea suave. En ese caso, Puedes usar el método getCoalescedEvents en el evento del puntero para obtener información sobre esos elementos. eventos combinados.

getCoalescedEvents
Figura 9: Ruta de gesto táctil suave a la izquierda, ruta limitada fusionada a la derecha
.
window.addEventListener('pointermove', event => {
    const events = event.getCoalescedEvents();
    for (let event of events) {
        const x = event.pageX;
        const y = event.pageY;
        // draw a line using x and y coordinates.
    }
});

Próximos pasos

En esta serie, hemos hablado del funcionamiento interno de un navegador web. Si nunca pensaste en por qué Las Herramientas para desarrolladores recomiendan agregar {passive: true} a tu controlador de eventos o la razón por la que podrías escribir async. en tu etiqueta de secuencia de comandos, espero que esta serie aclare por qué un navegador los necesita para brindar una experiencia web más rápida y fluida.

Usar Lighthouse

Si deseas que tu código sea agradable para el navegador, pero no sabes por dónde empezar, Lighthouse es una herramienta que ejecuta una auditoría de cualquier sitio web y te ofrece una informar sobre lo que se está haciendo bien y lo que debe mejorarse. Lee la lista de auditorías te da una idea de qué es importante para un navegador.

Más información para medir el rendimiento

Los ajustes de rendimiento pueden variar según el sitio, por lo que es fundamental que lo midas de tu sitio y decidir cuál es la mejor para él. El equipo de Herramientas para desarrolladores de Chrome tiene algunos instructivos cómo medir el rendimiento de tu sitio.

Agrega la política de funciones a tu sitio

Si desea realizar un paso adicional, la Política de funciones es una nueva de la plataforma web que pueden ser una barrera de seguridad cuando estás creando tu proyecto. Activando La política de funciones garantiza el comportamiento determinado de tu app y evita que se cometan errores. Por ejemplo, si quieres asegurarte de que tu app nunca bloquee el análisis, puedes ejecutarla en de secuencias de comandos síncronas. Cuando se habilita sync-script: 'none', el código JavaScript que bloquea los analizadores evitar que se ejecute. Esto evita que tu código bloquee el analizador, y las no necesita preocuparse por pausar el analizador.

Conclusión

Gracias

Cuando empecé a crear sitios web, casi solo me importaba cómo escribiría mi código y qué me ayudaría a ser más productivo. Esos puntos son importantes, pero también deberíamos pensar en cómo navegador toma el código que escribimos. Los navegadores modernos han invertido y siguen invirtiendo en formas de proporcionar una mejor experiencia web a los usuarios. Ser amable con el navegador al organizar nuestro código, a su vez, mejora la experiencia del usuario. ¡Espero que te unas a mí en la misión de ser amable con los navegadores!

Muchas gracias a todos los que revisaron los primeros borradores de esta serie, incluidos, entre otros, a): Alex Russell, Paul Ireland, Meggin Kearney, Eric Bidelman, Mathias Bynens, Addy Osmani: Kinuko Yasuda: Nasko Oskov: y Charlie Reis.

¿Te gustó esta serie? Si tienes preguntas o sugerencias para la próxima publicación, Me encantaría tener noticias tuyas en la sección de comentarios a continuación o de @kosamari. en Twitter.