Optimiser le First Input Delay

Comment répondre plus rapidement aux interactions des utilisateurs

J'ai cliqué, mais rien ne s'est passé ! Pourquoi ne puis-je pas interagir avec cette page ? 😢

Le First Contentful Paint (FCP) et le Largest Contentful Paint (LCP) sont tous deux des métriques qui mesurent le temps nécessaire pour que le contenu s'affiche visuellement (peindre) sur une page. Bien qu'important, les temps de rendu ne tiennent pas compte de la réactivité au chargement, c'est-à-dire de la rapidité avec laquelle une page réagit aux interactions des utilisateurs.

Le délai de première entrée (FID) est une métrique Core Web Vitals qui enregistre la première impression d'un utilisateur concernant l'interactivité et la réactivité d'un site. Il mesure le délai entre le moment où un utilisateur interagit pour la première fois avec une page et le moment où le navigateur est réellement en mesure de répondre à cette interaction. FID est une métrique de champ qui ne peut pas être simulée dans un environnement d'atelier. Une interaction utilisateur réelle est nécessaire pour mesurer le délai de réponse.

Les bonnes valeurs fidélisent sont de 2,5 secondes, les valeurs médiocres sont supérieures à 4 secondes et les valeurs intermédiaires doivent être améliorées.

Pour prédire le FID dans l'atelier, nous vous recommandons d'utiliser le temps de blocage total (TBT). Ils mesurent des éléments différents, mais les améliorations de la méthode de contrôle à distance correspondent généralement à des améliorations du FID.

Un FID médiocre est principalement dû à une exécution JavaScript intensive. En optimisant la façon dont JavaScript analyse, compile et exécute votre page Web, vous pouvez réduire directement le FID.

Exécution JavaScript intensive

Le navigateur ne peut pas répondre à la plupart des entrées utilisateur lorsqu'il exécute JavaScript sur le thread principal. En d'autres termes, le navigateur ne peut pas répondre aux interactions de l'utilisateur tant que le thread principal est occupé. Pour améliorer cela:

Divisez les longues tâches

Si vous avez déjà essayé de réduire la quantité de code JavaScript chargé sur une seule page, il peut être utile de décomposer le code de longue durée en tâches asynchrones plus petites.

Les tâches longues sont des périodes d'exécution JavaScript pendant lesquelles les utilisateurs peuvent constater que votre interface utilisateur ne répond pas. Tout morceau de code qui bloque le thread principal pendant 50 ms ou plus peut être caractérisé en tant que tâche longue. Les tâches longues sont un signe de surcharge potentielle de JavaScript (le chargement et l'exécution étant plus importants que ce dont l'utilisateur peut avoir besoin actuellement). Diviser les tâches longues peut réduire le délai de saisie sur votre site.

Tâches longues dans les outils pour les développeurs Chrome
Les outils pour les développeurs Chrome visualisent les tâches longues dans le panneau "Performances"

Le FID devrait s'améliorer sensiblement à mesure que vous adoptez les bonnes pratiques telles que la division du code et la séparation de vos tâches longues. Bien que la fonctionnalité "TBT" ne soit pas une métrique de champ, elle est utile pour vérifier la progression vers l'amélioration finale à la fois du délai avant interactivité (TTI) et du FID.

Optimiser votre page pour qu'elle soit prête à interagir avec les autres

Il existe un certain nombre de causes courantes à l'absence de scores FID et Totaux médiocres dans les applications Web qui s'appuient fortement sur JavaScript:

L'exécution du script propriétaire peut retarder la préparation des interactions

  • L'augmentation de la taille de JavaScript, les temps d'exécution importants et la fragmentation inefficace peuvent ralentir la réponse d'une page aux entrées utilisateur, et avoir un impact sur le FID, la TTC et le TTI. Le chargement progressif du code et des fonctionnalités peut aider à répartir ce travail et à améliorer la préparation aux interactions.
  • Les applications affichées côté serveur peuvent donner l'impression que des pixels s'affichent rapidement à l'écran, mais méfiez-vous des interactions utilisateur bloquées par des exécutions de scripts volumineuses (par exemple, une réhydratation pour connecter des écouteurs d'événements). Si vous utilisez le fractionnement de code basé sur le routage, cette opération peut prendre plusieurs centaines de millisecondes, voire quelques secondes. Envisagez de déplacer davantage de logique côté serveur ou de générer plus de contenu de manière statique pendant la compilation.

Vous trouverez ci-dessous les scores de navigation détaillée avant et après optimisation du chargement des scripts propriétaires pour une application. En déplaçant, en dehors du chemin critique, le chargement (et l'exécution) coûteux d'un script pour un composant non essentiel, les utilisateurs ont pu interagir avec la page beaucoup plus rapidement.

Améliorations du score de navigation à long terme dans Lighthouse après optimisation du script propriétaire.

L'extraction de données peut influer sur de nombreux aspects de la préparation des interactions.

  • Le fait d'attendre une série de récupérations en cascade (par exemple, JavaScript et les extractions de données pour les composants) peut avoir une incidence sur la latence des interactions. Essayez de minimiser la dépendance aux récupérations de données en cascade.
  • Les grands datastores intégrés peuvent transmettre le temps d'analyse HTML et avoir un impact sur les métriques de peinture et d'interaction. Essayez de minimiser la quantité de données qui doivent être post-traitées côté client.

L'exécution d'un script tiers peut également retarder la latence des interactions

  • De nombreux sites incluent des balises et des analyses tierces qui peuvent occuper le réseau et rendre le thread principal régulièrement qui ne répond pas, ce qui réduit la latence des interactions. Explorez le chargement à la demande de code tiers (par exemple, ne chargez pas les annonces dans la partie en dessous de la ligne de flottaison avant d'avoir fait défiler la page plus près de la fenêtre d'affichage).
  • Dans certains cas, les scripts tiers peuvent préempter les scripts propriétaires en termes de priorité et de bande passante sur le thread principal, ce qui retarde également le délai de préparation d'une page pour les interactions. Essayez d'abord de charger en priorité ce qui, selon vous, est le plus intéressant pour les utilisateurs.

Utiliser un nœud de calcul Web

Un thread principal bloqué est l'une des principales causes de retard d'entrée. Les nœuds de calcul Web permettent d'exécuter JavaScript sur un thread d'arrière-plan. Déplacer des opérations qui ne sont pas liées à l'UI vers un thread de nœud de calcul distinct peut réduire le temps de blocage du thread principal et, par conséquent, améliorer le FID.

Envisagez d'utiliser les bibliothèques suivantes pour faciliter l'utilisation des workers Web sur votre site:

  • Comlink: bibliothèque d'aide qui extrait postMessage et facilite son utilisation.
  • Workway: un exportateur de travailleurs Web à usage général
  • Workerize: déplacer un module vers un worker Web

Réduire le temps d'exécution JavaScript

En limitant la quantité de code JavaScript sur votre page, vous réduisez le temps que le navigateur doit consacrer à l'exécution du code JavaScript. Cela réduit la vitesse à laquelle le navigateur peut commencer à répondre aux interactions des utilisateurs.

Pour réduire la quantité de code JavaScript exécuté sur votre page:

  • Différer le code JavaScript inutilisé
  • Réduire le nombre de polyfills inutilisés

Différer le code JavaScript inutilisé

Par défaut, tout JavaScript bloque l'affichage. Lorsque le navigateur rencontre un tag de script associé à un fichier JavaScript externe, il doit mettre en pause ce qu'il fait, puis télécharger, analyser, compiler et exécuter ce code JavaScript. Par conséquent, vous ne devez charger que le code nécessaire pour la page ou répondre à une entrée utilisateur.

L'onglet Couverture des outils pour les développeurs Chrome peut vous indiquer la quantité de code JavaScript qui n'est pas utilisé sur votre page Web.

Onglet "Couverture"

Pour réduire le nombre de ressources JavaScript inutilisées:

  • Diviser votre bundle en plusieurs fragments
  • Différez le code JavaScript non critique, y compris les scripts tiers, à l'aide de async ou defer

La division du code consiste à diviser un seul grand bundle JavaScript en fragments plus petits pouvant être chargés de manière conditionnelle (on parle également de chargement différé). La plupart des navigateurs récents acceptent la syntaxe d'importation dynamique, qui permet d'extraire des modules à la demande:

import('module.js').then((module) => {
  // Do something with the module.
});

En important dynamiquement le code JavaScript lors de certaines interactions utilisateur (comme la modification d'un itinéraire ou l'affichage d'une fenêtre modale), vous avez la garantie que le code qui n'est pas utilisé pour le chargement initial de la page n'est récupéré que lorsque cela est nécessaire.

Outre la prise en charge générale des navigateurs, la syntaxe d'importation dynamique peut être utilisée dans de nombreux systèmes de compilation différents.

  • Si vous utilisez webpack, Rollup ou Parcel en tant que bundler de modules, profitez de leur compatibilité avec l'importation dynamique.
  • Les frameworks côté client, tels que React, Angular et Vue fournissent des abstractions qui facilitent le chargement différé au niveau des composants.

Hormis la division du code, utilisez toujours async ou defer pour les scripts qui ne sont pas nécessaires pour le contenu critique ou au-dessus de la ligne de flottaison.

<script defer src="…"></script>
<script async src="…"></script>

Sauf raison spécifique de ne pas le faire, tous les scripts tiers doivent être chargés par défaut avec defer ou async.

Réduire le nombre de polyfills inutilisés

Si vous créez votre code à l'aide d'une syntaxe JavaScript moderne et faites référence à des API de navigateurs modernes, vous devrez le transpiler et inclure des polyfills pour qu'il fonctionne dans les anciens navigateurs.

L'ajout de polyfills et de code transpilé à votre site représente un problème de performances majeur : le téléchargement des navigateurs récents n'est pas nécessaire s'ils n'en ont pas besoin. Pour réduire la taille JavaScript de votre application, réduisez autant que possible les polyfills inutilisés et limitez leur utilisation aux environnements où ils sont nécessaires.

Pour optimiser l'utilisation du polyfill sur votre site:

  • Si vous utilisez Babel comme transpilateur, utilisez @babel/preset-env pour n'inclure que les polyfills nécessaires aux navigateurs que vous prévoyez de cibler. Pour Babel 7.9, activez l'option bugfixes pour réduire davantage les polyfills inutiles.
  • Utilisez le modèle module/nomodule pour fournir deux bundles distincts (@babel/preset-env est également compatible avec target.esmodules).

    <script type="module" src="modern.js"></script>
    <script nomodule src="legacy.js" defer></script>
    

    De nombreuses fonctionnalités ECMAScript plus récentes compilées avec Babel sont déjà compatibles avec les environnements compatibles avec les modules JavaScript. Ainsi, vous simplifiez la procédure qui vous permet de vous assurer que seul le code transpilé est utilisé pour les navigateurs qui en ont réellement besoin.

Outils pour les développeurs

Plusieurs outils permettent de mesurer et de déboguer le FID:

Nous remercions Philip Walton, Kayce Basques, Ilya Grigorik et Annie Sullivan pour leurs avis.