Optimiser l'interaction pour la page suivante

Découvrez comment optimiser l'interaction de votre site Web avec Next Paint.

Interaction to Next Paint (INP) est une métrique Core Web Vitals stable. Elle évalue la réactivité globale d'une page aux interactions des utilisateurs en observant la latence de toutes les interactions éligibles qui se produisent tout au long de la durée de vie de la visite d'un utilisateur sur une page. La valeur INP finale correspond à l'interaction la plus longue observée (en ignorant parfois les anomalies).

Pour offrir une expérience utilisateur de qualité, les sites Web doivent s'efforcer d'avoir une Interaction to Next Paint de 200 millisecondes ou moins. Pour vous assurer d'atteindre cet objectif pour la plupart de vos utilisateurs, nous vous recommandons de mesurer le 75e centile de chargements de pages, segmenté selon les appareils mobiles et les ordinateurs.

Les bonnes valeurs INP sont de 200 millisecondes ou moins, les valeurs médiocres sont supérieures à 500 millisecondes et les valeurs intermédiaires doivent être améliorées.

En fonction du site Web, il peut y avoir peu ou pas d'interactions, telles que des pages contenant principalement du texte et des images avec peu ou pas d'éléments interactifs. Ou, dans le cas de sites Web tels que des éditeurs de texte ou des jeux, il peut y avoir des centaines, voire des milliers, d'interactions. Dans les deux cas, lorsque l'INP est élevé, l'expérience utilisateur est menacée.

Améliorer INP demande du temps et des efforts, mais la récompense est une meilleure expérience utilisateur. Dans ce guide, nous allons vous expliquer comment améliorer INP.

Déterminer la cause d'un INP faible

Avant de pouvoir corriger les interactions lentes, vous devez disposer de données vous permettant de savoir si l'INP de votre site Web est faible ou si vous devez l'améliorer. Une fois que vous disposez de ces informations, vous pouvez accéder à l'atelier pour commencer à diagnostiquer les interactions lentes et trouver une solution.

Identifier les interactions lentes sur le terrain

Idéalement, votre parcours d'optimisation de l'INP commencera avec les données de terrain. Dans le meilleur des cas, les données réelles fournies par un fournisseur RUM (Real User Monitoring) vous fournissent non seulement la valeur INP d'une page, mais également des données contextuelles qui mettent en évidence l'interaction spécifique responsable de la valeur INP elle-même, que l'interaction s'est produite pendant ou après le chargement de la page, le type d'interaction (clic, pression sur une touche ou appui) et d'autres informations précieuses.

Si vous ne faites pas appel à un fournisseur de RUM pour obtenir des données réelles, le guide des données réelles sur le terrain de l'INP vous conseille d'utiliser le rapport sur l'expérience utilisateur de Chrome (CrUX) via PageSpeed Insights pour combler les lacunes. CrUX est l'ensemble de données officiel du programme Core Web Vitals. Elle fournit un résumé général des métriques de millions de sites Web, y compris INP. Cependant, CrUX ne fournit souvent pas les données contextuelles qu'un fournisseur de RUM vous fournit pour vous aider à analyser les problèmes. C'est pourquoi nous recommandons toujours aux sites d'utiliser un fournisseur de RUM dans la mesure du possible, ou d'implémenter leur propre solution de RUM pour compléter ce qui est disponible dans CrUX.

Diagnostiquer les interactions lentes dans l'atelier

Idéalement, vous commencerez les tests dans l'atelier une fois que vous disposerez de données réelles suggérant que vos interactions sont lentes. En l'absence de données réelles, certaines stratégies permettent d'identifier les interactions lentes en laboratoire. Ces stratégies incluent le suivi des parcours utilisateur courants et le test des interactions tout au long du processus, ainsi que l'interaction avec la page lors du chargement (lorsque le fil de discussion principal est souvent le plus chargé) afin de détecter les interactions lentes pendant cette partie cruciale de l'expérience utilisateur.

Optimiser les interactions

Une fois que vous avez identifié une interaction lente et que vous pouvez la reproduire manuellement dans l'atelier, l'étape suivante consiste à l'optimiser. Les interactions peuvent être divisées en trois phases:

  1. Le délai d'entrée, qui commence lorsque l'utilisateur commence une interaction avec la page et se termine lorsque les rappels d'événement pour l'interaction commencent à s'exécuter.
  2. Le temps de traitement, qui correspond au temps nécessaire pour que les rappels d'événements s'exécutent jusqu'à la fin.
  3. Le délai de présentation, c'est-à-dire le temps nécessaire au navigateur pour présenter l'image suivante contenant le résultat visuel de l'interaction.

La somme de ces trois phases correspond à la latence totale d'interaction. Chaque phase d'une interaction contribue à la latence totale de l'interaction. Il est donc important de savoir comment optimiser chaque partie de l'interaction pour qu'elle s'exécute le moins de temps possible.

Identifier et réduire le délai d'entrée

Lorsqu'un utilisateur interagit avec une page, la première partie de cette interaction est le délai d'entrée. En fonction des autres activités de la page, les délais d'entrée peuvent être de durée considérable. Cela peut être dû à une activité sur le thread principal (peut-être au chargement, à l'analyse et à la compilation de scripts), à la gestion de la récupération, aux fonctions de minuteur, ou même à d'autres interactions qui se succèdent rapidement et se chevauchent.

Quelle que soit la source du délai d'entrée d'une interaction, vous devez le réduire au minimum afin que les interactions puissent commencer à exécuter des rappels d'événement dès que possible.

Relation entre l'évaluation des scripts et les longues tâches au démarrage

Le démarrage est un aspect essentiel de l'interactivité dans le cycle de vie de la page. Lorsqu'une page se charge, elle s'affiche dans un premier temps. Toutefois, n'oubliez pas que le rendu ne signifie pas qu'elle est chargée terminée. Selon la quantité de ressources dont une page a besoin pour devenir entièrement fonctionnelle, il est possible que les utilisateurs tentent d'interagir avec la page alors qu'elle est encore en cours de chargement.

L'évaluation de script est une fonctionnalité qui permet de prolonger le délai d'entrée d'une interaction lors du chargement d'une page. Une fois qu'un fichier JavaScript a été récupéré à partir du réseau, le navigateur doit encore travailler avant de pouvoir exécuter JavaScript. Pour ce faire, il faut analyser un script pour s'assurer que sa syntaxe est valide, le compiler en bytecode, puis l'exécuter.

Selon la taille d'un script, cette tâche peut introduire de longues tâches sur le thread principal, ce qui retarde la réponse du navigateur aux autres interactions utilisateur. Pour que votre page reste réactive aux entrées utilisateur lors de son chargement, il est important de comprendre ce que vous pouvez faire afin de réduire le risque de longues tâches pendant le chargement. Ainsi, la page reste réactive.

Optimiser les rappels d'événement

Le délai d'entrée n'est que la première partie de ce que l'INP mesure. Vous devez également vous assurer que les rappels d'événements exécutés en réponse à une interaction de l'utilisateur peuvent se terminer le plus rapidement possible.

Cèdent souvent au thread principal

Le meilleur conseil général pour optimiser les rappels d'événement est de les modifier le moins possible. Cependant, votre logique d'interaction peut être complexe et vous ne pourrez peut-être que réduire légèrement le travail qu'elle effectue.

Si c'est le cas pour votre site Web, vous pouvez ensuite scinder le travail dans les rappels d'événements en tâches distinctes. Cela évite que le travail collectif devienne une longue tâche qui bloque le thread principal, ce qui permet à d'autres interactions qui, autrement, attendraient que le thread principal s'exécute plus tôt.

setTimeout est un moyen de répartir les tâches, car le rappel qui lui est transmis s'exécute dans une nouvelle tâche. Vous pouvez utiliser setTimeout seul ou extraire son utilisation dans une fonction distincte pour un rendement plus ergonomique.

Il est préférable de céder sans discernement plutôt que de ne pas donner du tout. Il existe toutefois un moyen plus nuancé de céder au thread principal, ce qui implique de ne céder qu'immédiatement après un rappel d'événement qui met à jour l'interface utilisateur afin que la logique de rendu puisse s'exécuter plus tôt.

Cédez pour permettre le rendu plus rapide

Une technique de rendement plus avancée consiste à structurer le code dans vos rappels d'événements afin de limiter ce qui est exécuté à la seule logique requise pour appliquer des mises à jour visuelles à l'image suivante. Tout le reste peut être reporté à une tâche ultérieure. Cela permet non seulement de rendre les rappels légers et agiles, mais aussi d'améliorer le délai d'affichage des interactions en empêchant les mises à jour visuelles de bloquer le code de rappel d'événement.

Par exemple, imaginez un éditeur de texte enrichi qui met en forme le texte à mesure que vous saisissez du texte, mais qui actualise d'autres aspects de l'interface utilisateur en fonction de ce que vous avez écrit (comme le nombre de mots, la mise en évidence des fautes d'orthographe et d'autres commentaires visuels importants). En outre, l'application peut avoir besoin d'enregistrer ce que vous avez écrit afin de ne pas perdre de travail si vous quittez et revenez.

Dans cet exemple, les quatre choses suivantes doivent se produire en réponse aux caractères saisis par l'utilisateur. Cependant, seul le premier élément doit être effectué avant que l’image suivante ne soit présentée.

  1. Modifiez la zone de texte avec ce que l'utilisateur a saisi et appliquez la mise en forme requise.
  2. Mettez à jour la partie de l'interface utilisateur qui affiche le nombre actuel de mots.
  3. Exécutez la logique pour vérifier qu'il n'y a pas de faute d'orthographe.
  4. Enregistrez les modifications les plus récentes (localement ou dans une base de données distante).

Pour ce faire, le code peut se présenter comme suit:

textBox.addEventListener('input', (inputEvent) => {
  // Update the UI immediately, so the changes the user made
  // are visible as soon as the next frame is presented.
  updateTextBox(inputEvent);

  // Use `setTimeout` to defer all other work until at least the next
  // frame by queuing a task in a `requestAnimationFrame()` callback.
  requestAnimationFrame(() => {
    setTimeout(() => {
      const text = textBox.textContent;
      updateWordCount(text);
      checkSpelling(text);
      saveChanges(text);
    }, 0);
  });
});

La visualisation suivante montre comment le report des mises à jour non critiques jusqu'à la fin de l'image suivante peut réduire le temps de traitement et donc la latence globale des interactions.

Représentation d'une interaction au clavier et des tâches qui s'ensuivent dans deux scénarios. Dans la figure du haut, la tâche critique de rendu et toutes les tâches en arrière-plan suivantes s'exécutent de manière synchrone jusqu'à ce que l'opportunité de présenter un frame soit disponible. Dans la figure du bas, la tâche essentielle de rendu s'exécute en premier, puis est transférée au thread principal pour présenter une nouvelle image plus tôt. Les tâches en arrière-plan s'exécutent ensuite.
Cliquez sur la figure ci-dessus pour afficher une version en haute résolution.

Bien que l'utilisation de setTimeout() dans un appel requestAnimationFrame() de l'exemple de code précédent soit certes un peu ésotérique, il s'agit d'une méthode efficace qui fonctionne dans tous les navigateurs pour s'assurer que le code non critique ne bloque pas le frame suivant.

Éviter le thrashing de mise en page

Le thrashing (parfois appelé "mise en page synchrone forcée") est un problème de performances d'affichage lorsque la mise en page se produit de manière synchrone. Il se produit lorsque vous mettez à jour des styles en JavaScript, puis que vous les lisez dans la même tâche. De nombreuses propriétés en JavaScript peuvent entraîner le thrashing de mise en page.

Visualisation du thrashing de mise en page dans le panneau "Performances" des outils pour les développeurs Chrome.
Exemple de thrashing de mise en page présenté dans le panneau "Performances" des outils pour les développeurs Chrome. Les tâches de rendu qui impliquent un thrashing de mise en page sont signalées par un triangle rouge dans l'angle supérieur droit de la partie de la pile d'appel, souvent intitulée Recalculate Style (Recalculer le style) ou Layout (Mise en page).

Le thrashing de mise en page constitue un goulot d'étranglement des performances. En effet, en modifiant les styles, puis en demandant immédiatement les valeurs de ces styles en JavaScript, le navigateur est forcé à effectuer un travail de mise en page synchrone qu'il aurait pu attendre d'exécuter de manière asynchrone plus tard après l'exécution des rappels d'événements.

Réduire le délai de présentation

Le délai de présentation d'un marque d'interaction s'étend entre le moment où les rappels d'événements d'une interaction ont terminé l'exécution et le moment où le navigateur est en mesure de peindre le frame suivant, qui affiche les modifications visuelles qui en résultent.

Réduire la taille du DOM

Lorsque le DOM d'une page est de petite taille, l'affichage se termine généralement rapidement. Toutefois, lorsque les DOM deviennent très volumineux, le travail de rendu tend à s'adapter à l'augmentation de la taille du DOM. La relation entre le travail de rendu et la taille du DOM n'est pas linéaire, mais les grands DOM nécessitent plus de travail que les petits DOM. Un DOM volumineux pose problème dans deux cas:

  1. Pendant le rendu initial de la page, lorsqu'un grand DOM nécessite beaucoup de travail pour afficher l'état initial de la page.
  2. En réponse à une interaction utilisateur, lorsqu'un grand DOM peut rendre les mises à jour de rendu très coûteuses, et donc augmenter le temps nécessaire au navigateur pour présenter le frame suivant.

Gardez à l'esprit que, dans certains cas, il n'est pas possible de réduire considérablement les DOM volumineux. Il existe des méthodes que vous pouvez adopter pour réduire la taille du DOM, comme aplatir votre DOM ou l'ajouter au DOM lors des interactions avec les utilisateurs pour réduire la taille initiale de votre DOM. Toutefois, ces techniques ne sont pas toujours efficaces.

Utiliser content-visibility pour afficher en différé des éléments hors écran

Pour limiter le travail d'affichage lors du chargement de la page et le travail d'affichage en réponse aux interactions des utilisateurs, vous pouvez vous appuyer sur la propriété CSS content-visibility, qui revient à afficher des éléments en différé à mesure qu'ils s'approchent de la fenêtre d'affichage. Bien qu'il soit parfois nécessaire de s'entraîner à utiliser efficacement content-visibility, il peut être utile de vérifier si le délai d'affichage obtenu est plus court, ce qui peut améliorer l'INP de votre page.

Tenez compte des coûts de performance lors de l'affichage de code HTML avec JavaScript.

S'il y a du code HTML, y compris une analyse HTML. Une fois que le navigateur a fini d'analyser le code HTML dans un DOM, il doit lui appliquer des styles, effectuer des calculs de mise en page, puis afficher cette mise en page. Il s'agit d'un coût inévitable, mais la façon d'afficher le code HTML est importante.

Lorsque le serveur envoie du code HTML, celui-ci arrive dans le navigateur sous forme de flux. Le traitement par flux signifie que la réponse HTML du serveur arrive en fragments. Le navigateur optimise la gestion d'un flux en analysant de manière incrémentielle des fragments de ce flux dès leur arrivée et en les affichant petit à petit. Il s'agit d'une optimisation des performances dans la mesure où le navigateur génère implicitement un rendement régulier et automatique lors du chargement de la page, et ce sans frais.

La première visite d'un site Web implique toujours une quantité de code HTML. Toutefois, une approche courante consiste à commencer par un minimum de code HTML, puis à utiliser JavaScript pour renseigner la zone de contenu. Les mises à jour ultérieures de cette zone de contenu sont également dues aux interactions des utilisateurs. C'est ce qu'on appelle généralement le modèle d'application monopage (SPA). L'un des inconvénients de ce modèle est qu'en affichant du code HTML avec JavaScript sur le client, vous obtenez non seulement le coût du traitement JavaScript pour créer ce code HTML, mais aussi le navigateur ne donne pas le rendement tant qu'il n'a pas fini d'analyser et de rendre ce code HTML.

Cependant, il est essentiel de se rappeler que même les sites Web qui ne sont pas des applications monopages implique probablement un rendu HTML via JavaScript à la suite des interactions. Ce n'est généralement pas un problème, tant que vous n'affichez pas de grandes quantités de code HTML sur le client, ce qui peut retarder la présentation de l'image suivante. Toutefois, il est important de comprendre les conséquences de cette approche sur les performances de l'affichage du code HTML dans le navigateur, ainsi que son impact sur la réactivité de votre site Web aux entrées utilisateur si vous affichez beaucoup de code HTML via JavaScript.

Conclusion

L'amélioration de l'INP de votre site est un processus itératif. Si vous corrigez une interaction lente sur le terrain, il y a de fortes chances que vous commenciez à constater d'autres interactions lentes, que vous devrez également optimiser, surtout si votre site Web offre beaucoup d'interactivité.

La clé pour améliorer INP est la persistance. À terme, vous pouvez vérifier la réactivité de votre page à un endroit où les utilisateurs sont satisfaits de l'expérience que vous leur proposez. De plus, lorsque vous développez de nouvelles fonctionnalités pour vos utilisateurs, vous pouvez être amené à suivre le même processus d'optimisation des interactions qui leur sont spécifiques. Cela demandera du temps et des efforts, mais c'est du temps et des efforts bien utilisés.

Image héros de Unsplash, de David Pisnoy et modifiée conformément à la licence Unsplash.