Optimiser le chargement de scripts tiers dans Next.js

Découvrez ce qui se cache derrière le composant Script de Next.js, qui fournit une solution intégrée pour optimiser le chargement des scripts tiers.

Leena Sohoni
Leena Sohoni
Houssein Djirdeh
Houssein Djirdeh

Environ 45% des demandes émanant de sites Web diffusés sur des mobiles et des ordinateurs de bureau sont des demandes tierces, et 33% sont des scripts. La taille, la latence et le chargement des scripts tiers peuvent avoir un impact significatif sur les performances d'un site. Le composant de script Next.js s'accompagne de bonnes pratiques et de valeurs par défaut. Il aide les développeurs à intégrer des scripts tiers dans leurs applications tout en résolvant les problèmes de performances potentiels dès la première utilisation.

Scripts tiers et leur impact sur les performances

Les scripts tiers permettent aux développeurs Web d'exploiter des solutions existantes pour implémenter des fonctionnalités courantes et réduire le temps de développement. Toutefois, les créateurs de ces scripts ne sont généralement pas incités à prendre en compte l'impact sur les performances du site Web consommateur. Ces scripts sont également une boîte noire pour les développeurs qui les utilisent.

Les scripts représentent un nombre important d'octets tiers téléchargés par des sites Web pour différentes catégories de requêtes tierces. Par défaut, le navigateur donne la priorité aux scripts en fonction de leur emplacement dans le document, ce qui peut retarder la découverte ou l'exécution de scripts essentiels à l'expérience utilisateur.

Les bibliothèques tierces requises pour la mise en page doivent être chargées tôt pour afficher la page. Les tiers qui ne sont pas nécessaires pour l'affichage initial doivent être différés afin de ne pas bloquer d'autres traitements sur le thread principal. Lighthouse propose deux audits pour signaler les scripts qui bloquent l'affichage ou ceux qui bloquent les threads principaux.

Audits Lighthouse pour éliminer les ressources bloquant l'affichage et réduire l'utilisation par des tiers

Il est important de tenir compte de l'ordre de chargement des ressources de votre page afin que les ressources critiques ne soient pas retardées et que les ressources non critiques ne bloquent pas les ressources critiques.

Même s'il existe des bonnes pratiques permettant de réduire l'impact des tiers, tout le monde ne sait peut-être pas comment les mettre en œuvre pour chacun d'entre eux. Cela peut être compliqué pour les raisons suivantes:

  • En moyenne, les sites Web utilisent 21 à 23 tiers différents (y compris des scripts) sur les mobiles et les ordinateurs. L'utilisation et les recommandations peuvent varier en fonction de l'utilisation.
  • La mise en œuvre de nombreux tiers peut varier selon qu'un framework ou une bibliothèque d'interface utilisateur spécifiques sont utilisés.
  • De nouvelles bibliothèques tierces sont fréquemment introduites.
  • En raison des exigences commerciales variables liées à un même tiers, il est difficile pour les développeurs de standardiser son utilisation.

L'intérêt d'Aurora pour les scripts tiers

Une partie de la collaboration entre Aurora avec des frameworks et des outils Web Open Source consiste à fournir des valeurs par défaut fiables et des outils avisés pour aider les développeurs à améliorer certains aspects de l'expérience utilisateur, tels que les performances, l'accessibilité, la sécurité et l'aptitude mobile. En 2021, nous nous sommes efforcés d'aider les piles de frameworks à améliorer l'expérience utilisateur et leurs métriques Signaux Web essentiels.

Pour atteindre notre objectif d'amélioration des performances du framework, l'une des étapes les plus importantes a consisté à rechercher la séquence de chargement idéale de scripts tiers dans Next.js. Les frameworks tels que Next.js bénéficient d'un positionnement unique pour fournir des valeurs par défaut et des fonctionnalités utiles qui aident les développeurs à charger efficacement des ressources, y compris des tiers. Nous avons mené une étude approfondie des archives HTTP et des données Lighthouse afin d'identifier les blocs de rendu tiers les plus importants dans différents frameworks.

Pour résoudre le problème des scripts tiers qui bloquent le thread principal utilisés dans une application, nous avons créé le composant Script. Le composant encapsule les fonctionnalités de séquençage afin d'offrir aux développeurs de meilleurs contrôles pour le chargement des scripts tiers.

Séquençage de scripts tiers sans composant de framework

Pour réduire l'impact des scripts bloquant l'affichage, consultez les consignes disponibles pour charger et séquencer efficacement les scripts tiers:

  1. Utilisez l'attribut async ou defer avec les balises <script> qui indiquent au navigateur de charger des scripts tiers non critiques sans bloquer l'analyseur de documents. Les scripts qui ne sont pas requis pour le chargement initial de la page ou la première interaction de l'utilisateur peuvent être considérés comme non essentiels.

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. Établissez les premières connexions aux origines requises à l'aide de la préconnexion et de dns-prefetch. Les scripts essentiels pourront ainsi commencer à être téléchargés plus tôt.

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. Procédez au chargement différé des ressources tierces et des intégrations une fois que le contenu de la page principale est terminé ou lorsque l'utilisateur fait défiler la page jusqu'à la partie de la page où elles sont incluses.

Composant de script Next.js

Le composant Script Next.js implémente les méthodes ci-dessus pour séquencer les scripts et fournit un modèle permettant aux développeurs de définir leur stratégie de chargement. Une fois la stratégie appropriée spécifiée, elle se chargera de manière optimale sans bloquer d'autres ressources critiques.

Le composant Script s'appuie sur la balise HTML <script> et permet de définir la priorité de chargement des scripts tiers à l'aide de l'attribut de stratégie.

// Example for beforeInteractive:
<Script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver" strategy="beforeInteractive" />

// Example for afterInteractive (default):
<Script src="https://example.com/samplescript.js" />

// Example for lazyonload:
<Script src="https://connect.facebook.net/en_US/sdk.js" strategy="lazyOnload" />

L'attribut de stratégie peut prendre trois valeurs.

  1. beforeInteractive: cette option peut être utilisée pour les scripts critiques qui doivent s'exécuter avant que la page ne devienne interactive. Next.js s'assure que ces scripts sont injectés dans le code HTML initial sur le serveur et exécutés avant d'autres scripts JavaScript auto-groupés. La gestion du consentement, les scripts de détection de bots ou les bibliothèques d'aide nécessaires pour afficher le contenu critique sont de bons candidats pour cette stratégie.

  2. afterInteractive: stratégie appliquée par défaut. Elle équivaut au chargement d'un script avec l'attribut "defer". Il doit être utilisé pour les scripts que le navigateur peut exécuter une fois que la page est interactive (par exemple, les scripts d'analyse). Next.js injecte ces scripts côté client et s'exécutent une fois que la page est hydratée. Par conséquent, sauf indication contraire, tous les scripts tiers définis à l'aide du composant Script sont différés par Next.js, ce qui fournit une valeur par défaut forte.

  3. lazyOnload: cette option peut être utilisée pour charger des scripts basse priorité de manière différée lorsque le navigateur est inactif. Les fonctionnalités fournies par ces scripts ne sont pas requises dès que la page devient interactive (par exemple, les plug-ins de chat ou de réseaux sociaux).

En spécifiant la stratégie, les développeurs peuvent indiquer à Next.js comment leur application utilise un script. Cela permet au framework d'appliquer les optimisations et les bonnes pratiques pour charger le script tout en assurant la meilleure séquence de chargement.

À l'aide du composant Script, les développeurs peuvent insérer un script tiers n'importe où dans l'application pour les scripts tiers à chargement tardif, et au niveau du document pour les scripts critiques. Cela implique que le composant Script peut être placé au même endroit que le composant à l'aide du script. Après l'hydratation, le script est injecté dans l'en-tête du document initialement affiché ou dans la partie inférieure du corps, en fonction de la stratégie utilisée.

Mesurer l'impact

Nous avons utilisé les modèles de l'application de commerce et du blog de démarrage Next.js pour créer deux applications de démonstration qui ont permis de mesurer l'impact de l'inclusion de scripts tiers. Les outils tiers couramment utilisés pour Google Tag Manager et les intégrations de réseaux sociaux ont été d'abord inclus directement sur les pages de ces applications, puis via le composant Script. Nous avons ensuite comparé les performances de ces pages sur WebPageTest.

Scripts tiers dans une application de commerce Next.js

Des scripts tiers ont été ajoutés au modèle d'application de commerce pour la démonstration, comme indiqué ci-dessous.

Avant Après
Google Tag Manager avec les blocs d'annonces Composant de script avec stratégie = afterInteractive pour les deux scripts
Bouton "Suivre" Twitter sans asynchrone ni avec différé
Configuration de scripts et de composants de script pour la démonstration 1 avec deux scripts.

La comparaison suivante montre la progression visuelle des deux versions du kit de démarrage commercial Next.js. Comme vous pouvez le constater, le LCP se produit près d'une seconde plus tôt avec le composant Script activé et la bonne stratégie de chargement.

Comparaison de bandes de film montrant l&#39;amélioration du LCP

Scripts tiers dans un blog Next.js

Des scripts tiers ont été ajoutés à l'application de blog de démonstration, comme indiqué ci-dessous.

Avant Après
Google Tag Manager avec les blocs d'annonces Composant de script avec stratégie = lazyonload pour chacun des quatre scripts
Bouton "Suivre Twitter" avec asynchrone
Bouton "S'abonner" de YouTube sans synchrone ou différé
Bouton "Suivre" LinkedIn sans asynchrone ni avec différé
Configuration de scripts et de composants de script pour la démonstration 2 avec quatre scripts.
Vidéo montrant la progression du chargement de la page d&#39;index avec et sans le composant Script. Le composant Script offre une amélioration de 0,5 seconde du FCP.

Comme nous l'avons vu dans la vidéo, First Contentful Paint (FCP) intervient à 0,9 seconde sur la page sans le composant Script et 0,4 seconde avec le composant Script.

Étapes suivantes pour le composant Script

Bien que les options de stratégie pour afterInteractive et lazyOnload offrent un contrôle important sur les scripts bloquant l'affichage, nous étudions également d'autres options qui amélioreraient l'utilité du composant Script.

Utiliser des nœuds de calcul Web

Les web workers peuvent être utilisés pour exécuter des scripts indépendants sur des threads en arrière-plan, ce qui peut libérer le thread principal pour gérer les tâches de traitement de l'interface utilisateur et améliorer les performances. Les Web Workers sont particulièrement adaptés au déchargement du traitement JavaScript, plutôt qu'au travail de l'interface utilisateur, hors du thread principal. Les scripts utilisés pour le service client ou le marketing, qui n'interagissent généralement pas avec l'UI, peuvent être de bons candidats pour une exécution sur un thread d'arrière-plan. Une bibliothèque tierce légère, PartyTown, peut être utilisée pour isoler ces scripts dans un nœud de calcul Web.

Avec l'implémentation actuelle du composant de script Next.js, nous vous recommandons de reporter ces scripts sur le thread principal en définissant la stratégie sur afterInteractive ou lazyOnload. À l'avenir, nous proposerons d'introduire une nouvelle option de stratégie, 'worker', qui permettra à Next.js d'utiliser PartyTown ou une solution personnalisée pour exécuter des scripts sur des workers Web. N'hésitez pas à nous faire part de vos commentaires sur ce document RFC.

Réduire le CLS

Les intégrations tierces, telles que les publicités, les vidéos ou les flux de réseaux sociaux, peuvent entraîner des décalages de mise en page lors du chargement différé. Cela affecte l'expérience utilisateur et la métrique CLS (Cumulative Layout Shift) de la page. Vous pouvez réduire le CLS en spécifiant la taille du conteneur dans lequel l'intégration doit être chargée.

Vous pouvez utiliser le composant Script pour charger des intégrations qui peuvent entraîner des décalages de mise en page. Nous envisageons de l'améliorer pour proposer des options de configuration qui contribueront à réduire le CLS. Celui-ci peut être disponible dans le composant Script lui-même ou sous la forme d'un composant associé.

Composants du wrapper

La syntaxe et la stratégie de chargement permettant d'inclure des scripts tiers populaires tels que Google Analytics ou Google Tag Manager (GTM) sont généralement fixes. Ceux-ci peuvent être encapsulés dans des composants wrapper individuels pour chaque type de script. Les développeurs n'ont accès qu'à un ensemble minimal d'attributs spécifiques à l'application (tels que l'ID de suivi). Les composants Wrapper aident les développeurs à:

  1. Ce qui leur permet d'inclure plus facilement des tags de script populaires.
  2. S'assurer que le framework utilise en arrière-plan la stratégie la plus optimale.

Conclusion

Les scripts tiers sont généralement créés pour inclure des fonctionnalités spécifiques dans le site Web consommateur. Pour réduire l'impact des scripts non critiques, nous vous recommandons de les différer (ce qui est le cas par défaut du composant Script Next.js). Les développeurs sont assurés que les scripts inclus ne retarderont pas les fonctionnalités essentielles, sauf s'ils appliquent explicitement la stratégie beforeInteractive. Comme pour le composant de script Next.js, les développeurs de frameworks peuvent également envisager de créer ces fonctionnalités dans d'autres frameworks. Nous étudions activement la possibilité de proposer un composant similaire avec l'équipe Nuxt.js. Suite à vos commentaires, nous espérons également améliorer le composant Script pour couvrir d'autres cas d'utilisation.

Remerciements

Merci à Kara Erickson, Janicklas Ralph, Katie Hempenius, Philip Walton, Jeremy Wagner et Addy Osmani pour leurs commentaires sur ce post.