Au cœur du navigateur Web moderne (partie 4)

Mariko Kosaka

L'entrée est envoyée au compositeur

Ceci est la dernière des quatre parties de notre série d'articles de blog consacrées à Chrome. en examinant comment il gère notre code pour afficher un site Web. Dans l'article précédent, nous avons étudié le processus de rendu et découvert le compositeur. Dans ce post, nous allons comment le compositeur permet une interaction fluide lorsqu'une entrée utilisateur est saisie.

Saisir les événements du point de vue du navigateur

Lorsque vous entendez "Événements d'entrée" vous pourriez ne penser qu’à une saisie dans une zone de texte ou à un clic de souris, mais du point de vue du navigateur, la saisie désigne tout geste de l'utilisateur. Le défilement de la molette de la souris est une entrée et un événement tactile ou au passage de la souris est également un événement d'entrée.

Lorsque l'utilisateur effectue un geste, comme un toucher sur un écran, le processus du navigateur est celui qui reçoit le geste d'ouverture. Toutefois, le processus du navigateur ne connaît que l'endroit où ce geste s'est produit, le contenu d'un onglet est géré par le processus du moteur de rendu. Le processus du navigateur envoie donc l'événement (comme touchstart) et ses coordonnées au processus du moteur de rendu. Le processus du moteur de rendu gère en trouvant la cible de l'événement et en exécutant les écouteurs d'événements associés.

événement d'entrée
Figure 1: Événement d'entrée acheminé via le processus du navigateur vers le processus du moteur de rendu

Le compositeur reçoit des événements d'entrée

Figure 2: Fenêtre d'affichage survolant les calques de page

Dans l'article précédent, nous avons vu comment le compositeur pouvait gérer de manière fluide le défilement en composant de couches rastérisées. Si aucun écouteur d'événements d'entrée n'est associé à la page, le fil de discussion du compositeur peut créer un nouveau cadre composite complètement indépendant du thread principal. Mais que se passe-t-il si un événement étaient associés à la page ? Comment le fil de discussion du compositeur déterminera-t-il si l'événement a besoin à traiter ?

Comprendre la région à défilement non rapide

L'exécution de JavaScript étant la tâche du thread principal, lorsqu'une page est composée, le thread du compositeur marque une région de la page à laquelle des gestionnaires d'événements sont associés en tant que "Région à défilement non rapide". Par contenant ces informations, le thread compositeur peut envoyer l'événement d'entrée au thread principal. si l'événement se produit dans cette région. Si l'événement d'entrée provient de l'extérieur de cette région, le thread compositeur continue la composition du nouveau frame sans attendre le thread principal.

zone à défilement limité et non rapide
Figure 3: Schéma de l'entrée décrite dans la zone à défilement non rapide

Soyez prudent lorsque vous écrivez des gestionnaires d'événements

La délégation d'événements est un modèle courant de gestion des événements en développement Web. Puisque les événements s'affichent, associer un gestionnaire d'événements à l'élément le plus haut et déléguer des tâches en fonction de la cible de l'événement Toi avez peut-être vu ou écrit du code comme ci-dessous.

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

Étant donné que vous n'avez besoin d'écrire qu'un seul gestionnaire d'événements pour tous les éléments, l'ergonomie de cet événement le schéma de délégation sont attrayants. Toutefois, si vous examinez ce code du point de vue du navigateur la page entière est désormais marquée comme une zone à défilement lent. Cela signifie que même si votre l'application ne se soucie pas des entrées provenant de certaines parties de la page, le fil de discussion du compositeur doit communiquer avec le thread principal et l'attendre chaque fois qu'un événement d'entrée se produit. Ainsi, la capacité de défilement fluide du compositeur est éliminée.

zone pleine page à défilement non rapide
Figure 4: Schéma de l'entrée décrite dans la zone à défilement non rapide recouvrant une page entière

Pour éviter cela, vous pouvez transmettre passive: true options dans votre événement l'écouteur. Cela indique au navigateur que vous souhaitez toujours écouter l'événement dans le thread principal, mais le compositeur peut aussi créer un frame.

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

Vérifier si l'événement peut être annulé

défilement de page
Figure 5: Page Web dont une partie de la page est définie sur un défilement horizontal

Imaginons que vous souhaitiez limiter la direction de défilement au défilement horizontal d'une page.

L'utilisation de l'option passive: true dans votre événement de pointeur signifie que le défilement de la page peut être fluide, mais le défilement vertical a peut-être commencé au moment où vous souhaitez preventDefault afin de limiter sens de défilement. Pour ce faire, utilisez la méthode 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});

Vous pouvez également utiliser une règle CSS telle que touch-action pour éliminer complètement le gestionnaire d'événements.

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

Trouver la cible de l'événement

test de positionnement
Figure 6: Fil principal examinant les enregistrements de peinture pour demander ce qui est dessiné au point x.y

Lorsque le thread compositeur envoie un événement d'entrée au thread principal, la première chose à exécuter est un hit. pour trouver l'événement cible. Le test de positionnement utilise les données d'enregistrement de peinture qui ont été générées dans le rendu pour savoir ce qui se trouve sous les coordonnées du point où l'événement s'est produit.

Réduire les distributions d'événements au thread principal

Dans le post précédent, nous avons parlé de la façon dont notre affichage standard actualise l'écran 60 fois par seconde et comment suivre la cadence pour une animation fluide. Pour la saisie, un écran tactile classique un appareil envoie des événements tactiles 60 à 120 fois par seconde et une souris classique 100 fois par seconde seconde. L'événement d'entrée est plus fidèle que ce que notre écran peut actualiser.

Si un événement continu tel que touchmove a été envoyé au thread principal 120 fois par seconde, il peut déclencher un nombre excessif de tests de positionnement et d'exécution de JavaScript, l'écran peut s'actualiser.

événements non filtrés
Figure 7: Événements qui inondent la chronologie des frames et provoquent des à-coups

Pour limiter les appels excessifs au thread principal, Chrome fusionne les événements continus (tels que wheel, mousewheel, mousemove, pointermove, touchmove) et retarde l'expédition jusqu'au juste avant le prochain requestAnimationFrame.

événements fusionnés
Figure 8: Même chronologie qu'avant, mais l'événement est fusionné et retardé

Tous les événements distincts tels que keydown, keyup, mouseup, mousedown, touchstart et touchend sont expédiés immédiatement.

Utiliser getCoalescedEvents pour obtenir des événements dans le cadre

Pour la plupart des applications Web, les événements fusionnés devraient suffire à offrir une bonne expérience utilisateur. Toutefois, si vous créez des éléments tels que le dessin d'une application et que vous placez un chemin d'accès basé sur touchmove, vous risquez de perdre des coordonnées entre les deux pour tracer une ligne lisse. Dans ce cas, vous pouvez utiliser la méthode getCoalescedEvents dans l'événement de pointeur pour obtenir des informations sur ces des événements fusionnés.

getCoalescedEvents
Figure 9: Chemin gestuel au toucher lisse à gauche et chemin limité fusionné à droite
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.
    }
});

Étapes suivantes

Dans cette série, nous avons abordé le fonctionnement interne d'un navigateur Web. Si vous n’avez jamais réfléchi à la raison Les outils de développement vous recommandent d'ajouter {passive: true} à votre gestionnaire d'événements ou d'expliquer pourquoi vous pourriez écrire async dans votre tag de script, j'espère que cette série vous aidera à comprendre pourquoi un navigateur a besoin de ces des informations pour offrir une expérience Web plus rapide et plus fluide.

Utiliser Lighthouse

Si vous voulez que votre code soit agréable pour le navigateur, mais que vous ne savez pas par où commencer, Lighthouse est un outil qui exécute un audit de n'importe quel site Web et vous donne une rendre compte de ce qui est bien fait et de ce qui doit être amélioré. En parcourant la liste des audits vous donne également une idée de ce qui compte pour un navigateur.

Découvrez comment mesurer les performances

Les ajustements de performances pouvant varier d'un site à l'autre, il est essentiel de mesurer les performances de votre site et décider ce qui convient le mieux à votre site. L'équipe des outils pour les développeurs Chrome propose des tutoriels comment mesurer les performances de votre site.

Ajouter une règle de fonctionnalité à votre site

Si vous souhaitez ajouter une étape supplémentaire, sachez que les Règles relatives aux fonctionnalités sont un nouveau de plateforme web qui peut être un garde-fous pour vous lorsque vous construisez votre projet. Activation... le règlement sur les fonctionnalités garantit le comportement précis de votre appli et vous évite de commettre des erreurs. Par exemple, pour vous assurer que votre application ne bloquera jamais l'analyse, vous pouvez l'exécuter sur de scripts synchrones. Lorsque sync-script: 'none' est activé, le code JavaScript bloquant de l'analyseur leur exécution. Ainsi, votre code ne bloque pas l'analyseur, et l'analyse le navigateur n'a pas à mettre en pause l'analyseur.

Conclusion

merci

Quand j'ai commencé à créer des sites Web, je ne me préoccupais presque que de la façon dont j'écrivais mon code et ce que m’aiderait à être plus productif. Ces points sont importants, mais nous devons également réfléchir à la façon dont le code que nous écrivons. Les navigateurs modernes investissent et continuent d'investir dans des moyens afin d'améliorer l'expérience des utilisateurs sur le Web. Être gentil avec le navigateur en organisant notre code, et améliorer l'expérience utilisateur. J'espère que vous me rejoindrez dans la quête d'une bonne expérience avec les navigateurs !

Merci beaucoup à tous ceux qui ont examiné les premières versions de cette série, y compris, mais sans s'y limiter à): Alex Russell, Paul Irish, Meggin Kearney, Eric Bidelman, Mathias Bynens, Addy Osmani, Kinuko Yasuda, Nasko Oskov, et Charlie Reis.

Avez-vous apprécié cette série ? Si vous avez des questions ou des suggestions pour le prochain post, N'hésitez pas à laisser un commentaire dans la section ci-dessous ou à envoyer un e-mail à l'adresse @kosamari. sur Twitter.