Optimiser le chargement de scripts tiers dans Next.js

Comprendre la vision 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

Environ 45% des demandes provenant de sites Web affichés sur mobile et ordinateur sont des demandes tierces, dont 33% sont des scripts. La taille, la latence et le chargement des scripts tiers peuvent avoir une incidence significative sur les performances d'un site. Le composant de script Next.js intègre les bonnes pratiques et les paramètres par défaut pour aider les développeurs à intégrer des scripts tiers dans leurs applications, tout en résolvant les éventuels problèmes de performances dès la première utilisation.

Scripts tiers et leur impact sur les performances

Les scripts tiers permettent aux développeurs Web d'exploiter les 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 utilisé. 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 hiérarchise les scripts en fonction de leur emplacement dans le document, ce qui peut retarder la découverte ou l'exécution des scripts essentiels à l'expérience utilisateur.

Les bibliothèques tierces requises pour la mise en page doivent être chargées au plus tôt pour afficher la page. Les tiers qui ne sont pas requis pour le rendu initial doivent être différés afin de ne pas bloquer les autres traitements sur le thread principal. Lighthouse comporte deux audits pour signaler les scripts bloquant l'affichage ou les scripts de blocage du thread principal.

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

Il est important de tenir compte de la séquence de chargement des ressources de votre page, de sorte que les ressources critiques ne soient pas retardées et que les ressources non critiques ne bloquent pas les ressources critiques.

Bien qu'il existe des bonnes pratiques pour réduire l'impact des tiers, tout le monde ne sait peut-être pas comment les mettre en œuvre pour chacun des tiers qu'il utilise. Cela peut être compliqué pour les raisons suivantes:

  • En moyenne, les sites Web font appel à 21 à 23 tiers différents, y compris des scripts, sur mobile et sur ordinateur. L'utilisation et les recommandations peuvent varier d'un produit à l'autre.
  • L'implémentation de nombreux tiers peut varier selon que vous utilisez un framework ou une bibliothèque d'UI spécifique.
  • Des bibliothèques tierces plus récentes sont fréquemment introduites.
  • Les différentes exigences métier liées au même tiers ne permettent pas aux développeurs de standardiser son utilisation.

Aurora se concentre sur les scripts tiers

Une partie de la collaboration d'Aurora avec les frameworks et outils Web Open Source consiste à fournir des paramètres 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'adaptation aux appareils mobiles. En 2021, nous nous sommes efforcés d'aider les piles de framework à améliorer l'expérience utilisateur et leurs métriques Core Web Vitals.

L'une des étapes les plus importantes pour atteindre notre objectif d'amélioration des performances du framework a consisté à étudier la séquence de chargement idéale des scripts tiers dans Next.js. Les frameworks tels que Next.js sont particulièrement bien placés pour fournir des fonctionnalités et des paramètres par défaut utiles qui aident les développeurs à charger efficacement des ressources, y compris des ressources tierces. Nous avons étudié de nombreuses données sur les archives HTTP et Lighthouse des données afin d'identifier les tiers qui bloquent le plus le rendu dans différents frameworks.

Pour résoudre le problème du blocage par le thread principal des scripts tiers utilisés dans une application, nous avons créé le composant Script. Le composant encapsule des fonctionnalités de séquençage pour offrir aux développeurs de meilleures commandes de chargement de scripts tiers.

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

Les conseils disponibles pour réduire l'impact des scripts bloquant l'affichage fournissent les méthodes suivantes pour charger et séquencer efficacement les scripts tiers:

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

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. Établissez des connexions précoces aux origines requises à l'aide de la préconnexion et de dns-prefetch. Le téléchargement des scripts critiques peut ainsi commencer plus tôt.

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. Effectuez un chargement différé des ressources tierces et des intégrations après la fin du chargement du contenu de la page principale 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 de script Next.js met en œuvre 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 de script s'appuie sur le tag HTML <script> et offre une option pour 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 accepter 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 garantit que ces scripts sont injectés dans le code HTML initial sur le serveur et exécutés avant les 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 à l'affichage du contenu critique sont de bons candidats pour cette stratégie.

  2. afterInteractive: stratégie par défaut appliquée. 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 la page 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, fournissant ainsi une valeur par défaut élevée.

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

Les développeurs peuvent spécifier la stratégie pour indiquer à Next.js comment leur application utilise un script. Cela permet au framework d'appliquer des optimisations et des bonnes pratiques pour charger le script tout en garantissant la séquence de chargement optimale.

Grâce à ce composant, les développeurs peuvent placer un script tiers n'importe où dans l'application pour les tiers à chargement tardif, et au niveau du document pour les scripts critiques. Cela signifie que le composant de script peut se trouver au même endroit que le composant utilisant le script. Après l'hydratation, le script est injecté dans l'en-tête du document initialement rendu ou au bas du corps du texte, selon 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'ajout de scripts tiers. Dans un premier temps, les outils tiers couramment utilisés pour Google Tag Manager et les intégrations sur les réseaux sociaux ont été 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 d'e-commerce pour la démonstration, comme indiqué ci-dessous.

Avant Après
Google Tag Manager avec le serveur Composant de script avec stratégie = afterInteractive pour les deux scripts
Bouton "Suivre" de Twitter sans asynchrone ni reporter
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 pour le commerce Next.js. Comme nous l'avons vu, le LCP apparaît près d'une seconde plus tôt avec le composant Script activé avec la stratégie de chargement appropriée.

Comparaison de bandes de films montrant l&#39;improvisation au 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 le serveur Composant de script avec stratégie = chargement différé pour chacun des quatre scripts
Bouton "Suivre" de Twitter avec asynchrone
Bouton "S'abonner" de YouTube sans flux asynchrone ni différé
Bouton "Suivre" de LinkedIn sans asynchrone ou report
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 de script. Le FCP a été amélioré de 0,5 seconde avec le composant Script.

Comme vous pouvez le voir dans la vidéo, l'événement First Contentful Paint (FCP) apparaît à 0,9 seconde sur la page sans le composant de script et à 0,4 seconde avec le composant de script.

Étapes suivantes pour le composant de script

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

Utiliser des nœuds de calcul Web

Les nœuds de calcul Web permettent d'exécuter des scripts indépendants sur des threads en arrière-plan. Cela permet de libérer le thread principal pour gérer les tâches de l'interface utilisateur et améliorer les performances. Les Web Workers sont particulièrement adaptés pour décharger du thread principal le traitement JavaScript plutôt que le travail de l'interface utilisateur. Les scripts utilisés pour le service client ou le marketing, qui n'interagissent généralement pas avec l'interface utilisateur, peuvent se prêter à l'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 différer 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 nœuds de calcul 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 des publicités, des vidéos ou des flux de réseaux sociaux, peuvent entraîner des décalages de mise en page en cas de chargement différé. Cela a une incidence sur l'expérience utilisateur et sur la métrique CLS (Cumulative Layout Shift) de la page. Vous pouvez réduire la CLS en spécifiant la taille du conteneur dans lequel l'intégration sera chargée.

Le composant "Script" permet de charger des éléments intégrés susceptibles de provoquer des décalages de mise en page. Nous envisageons de l'étendre à des options de configuration qui contribueront à réduire le CLS. Elle peut être disponible dans le composant de script lui-même ou en tant que composant compagnon.

Composants de l'enveloppe

La syntaxe et la stratégie de chargement permettant d'inclure des scripts tiers courants tels que Google Analytics ou Google Tag Manager (GTM) sont généralement fixes. Ils peuvent être encapsulés dans des composants wrapper individuels pour chaque type de script. Seul un ensemble minimal d'attributs propres à l'application (comme l'ID de suivi) sera mis à la disposition des développeurs. Les composants de l'enveloppe aideront les développeurs à:

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

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 que le composant Script Next.js fait par défaut. Les développeurs ont l'assurance que les scripts inclus ne retarderont pas les fonctionnalités critiques, sauf s'ils appliquent explicitement la stratégie beforeInteractive. Tout comme 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 aux commentaires que nous avons reçus, nous espérons également améliorer davantage 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.