Package Next.js permettant de gérer les bibliothèques tierces

En 2021, l'équipe Chrome Aurora a lancé le composant Script pour améliorer les performances de chargement des scripts tiers dans Next.js. Depuis son lancement, nous avons étendu ses fonctionnalités afin de faciliter et d'accélérer le chargement des ressources tierces pour les développeurs.

Cet article de blog présente les nouvelles fonctionnalités que nous avons publiées, en particulier la bibliothèque @next/third-parties, ainsi qu'un aperçu des futures initiatives de notre feuille de route.

Conséquences des scripts tiers sur les performances

41 % de l'ensemble des requêtes tierces sur les sites Next.js sont des scripts. Contrairement aux autres types de contenu, le téléchargement et l'exécution des scripts peuvent prendre un temps considérable, ce qui peut bloquer le rendu et retarder l'interactivité de l'utilisateur. Les données du rapport d'expérience utilisateur Chrome (CrUX) montrent que les sites Next.js qui chargent davantage de scripts tiers enregistrent des taux de réussite Interaction to Next Paint (INP) et Largest Contentful Paint (LCP) inférieurs.

Graphique à barres montrant une baisse du pourcentage de sites Next.js obtenant de bons scores INP et LCP en fonction du nombre de tiers chargés
Rapport CrUX de décembre 2023 (110 823 sites)

La corrélation observée dans ce graphique n'implique pas de causalité. Cependant, les tests en local fournissent des preuves supplémentaires que les scripts tiers ont un impact significatif sur les performances des pages. Par exemple, le graphique ci-dessous compare plusieurs métriques de laboratoire lorsqu'un conteneur Google Tag Manager, composé de 18 balises sélectionnées de manière aléatoire, est ajouté à Taxonomy, un exemple d'application Next.js populaire.

Graphique à barres montrant les différences entre les différentes métriques de laboratoire lorsqu'un site est chargé avec et sans Google Tag Manager
WebPageTest (Mobile 4G - Virginie États-Unis)

La documentation WebPageTest explique en détail comment ces temps sont mesurés. D'un coup d'œil, il est clair que toutes ces métriques de laboratoire sont affectées par le conteneur GTM. Par exemple, le Total Blocking Time (TBT) (temps de blocage total), un proxy de laboratoire utile qui se rapproche de l'INP, a augmenté de près de 20 fois.

Composant "Script"

Lorsque nous avons lancé le composant <Script> dans Next.js, nous avons veillé à l'introduire via une API conviviale ressemblant fortement à l'élément <script> traditionnel. Grâce à elle, les développeurs peuvent colocaliser un script tiers dans n'importe quel composant de leur application, et Next.js se chargera de séquencer le script une fois les ressources critiques chargées.

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

Des dizaines de milliers d'applications Next.js, y compris des sites populaires tels que Patreon, Target et Notion, utilisent le composant <Script>. Malgré son efficacité, certains développeurs ont exprimé des inquiétudes concernant les points suivants :

  • Où placer le composant <Script> dans une application Next.js tout en respectant les différentes instructions d'installation des différents fournisseurs tiers (expérience pour les développeurs).
  • Quelle stratégie de chargement est la plus optimale à utiliser pour différents scripts tiers (expérience utilisateur) ?

Pour répondre à ces deux préoccupations, nous avons lancé @next/third-parties, une bibliothèque spécialisée proposant un ensemble de composants et d'utilitaires optimisés adaptés aux tiers populaires.

Expérience pour les développeurs : gérer plus facilement les bibliothèques tierces

De nombreux scripts tiers sont utilisés par un pourcentage important de sites Next.js, Google Tag Manager étant le plus populaire, utilisé par 66 % des sites. @next/third-parties s'appuie sur le composant <Script> en introduisant des wrappers de niveau supérieur conçus pour simplifier l'utilisation de ces cas d'utilisation courants.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

Google Analytics, un autre script tiers très utilisé (52% des sites Next.js), dispose également d'un composant dédié lui-même.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties simplifie le processus de chargement des scripts couramment utilisés, mais il étend également notre capacité à développer des utilitaires pour d'autres catégories tierces, telles que les implémentations. Par exemple, les intégrations Google Maps et YouTube sont utilisées dans respectivement 8 % et 4 % des sites Web Next.js. Nous avons également publié des composants pour les charger plus facilement.

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

Expérience utilisateur : accélérer le chargement des bibliothèques tierces

Dans un monde idéal, chaque bibliothèque tierce largement adoptée serait entièrement optimisée, rendant inutiles les abstractions qui améliorent ses performances. Toutefois, en attendant que cela devienne une réalité, nous pouvons essayer d'améliorer leur expérience utilisateur lorsqu'ils sont intégrés via des frameworks populaires tels que Next.js. Nous pouvons tester différentes techniques de chargement, nous assurer que les scripts sont séquencés correctement et, au final, partager nos commentaires avec les fournisseurs tiers pour encourager les modifications en amont.

Prenons l'exemple des vidéos YouTube intégrées. Certaines implémentations alternatives offrent de bien meilleures performances que l'intégration native. Actuellement, le composant <YouTubeEmbed> exporté par @next/third-parties utilise lite-youtube-embed, qui, lors d'une démonstration dans une comparaison "Hello, World" Next.js, se charge beaucoup plus rapidement.

GIF montrant une comparaison du chargement de la page entre le composant d&#39;intégration YouTube et une iframe YouTube standard
WebPageTest (Mobile 4G - Virginie États-Unis)

De même, pour Google Maps, nous incluons loading="lazy" comme attribut par défaut pour l'intégration afin de nous assurer que la carte ne se charge que lorsqu'elle se trouve à une certaine distance de la fenêtre d'affichage. Cet attribut peut sembler évident à inclure, d'autant que la documentation de Google Maps l'inclut dans l'exemple d'extrait de code. Toutefois, seuls 45% des sites Next.js qui intègrent Google Maps utilisent loading="lazy".

Exécuter des scripts tiers dans un nœud de calcul Web

Une technique avancée que nous explorons dans @next/third-parties consiste à faciliter le transfert des scripts tiers vers un web worker. Popularisée par des bibliothèques telles que Partytown, cette approche peut réduire considérablement l'impact des scripts tiers sur les performances des pages en les déplaçant entièrement du thread principal.

Le GIF animé suivant montre les variations des tâches longues et du temps de blocage du thread principal lors de l'application de différentes stratégies <Script> à un conteneur GTM sur un site Next.js. Notez que même si le passage d'une option de stratégie à une autre ne retarde que l'exécution de ces scripts, le transfert de ces scripts vers un nœud de calcul Web élimine complètement le temps passé sur le thread principal.

GIF montrant les différences de temps de blocage du thread principal pour les différentes stratégies de script
WebPageTest (Mobile 4G - Virginia USA)

Dans cet exemple, le déplacement de l'exécution du conteneur GTM et des scripts de balise associés vers un nœud de calcul Web a réduit la TAT de 92%.

Notez que, si elle n'est pas gérée avec soin, cette technique peut casser silencieusement de nombreux scripts tiers, ce qui rend le débogage difficile. Dans les mois à venir, nous vérifierons si les composants tiers proposés par @next/third-parties fonctionnent correctement lorsqu'ils sont exécutés dans un worker Web. Si c'est le cas, nous nous efforcerons de fournir aux développeurs un moyen simple et facultatif d'utiliser cette technique.

Étapes suivantes

Au cours du développement de ce package, il est apparu clairement qu'il était nécessaire de centraliser les recommandations de chargement tiers afin que d'autres frameworks puissent également bénéficier des mêmes techniques sous-jacentes. Nous avons donc créé Third Party Capital, une bibliothèque qui utilise le format JSON pour décrire les techniques de chargement tierces, qui sert actuellement de base à @next/third-parties.

Nous allons continuer à améliorer les composants fournis pour Next.js et à inclure des utilitaires similaires dans d'autres frameworks et plates-formes CMS populaires. Nous collaborons actuellement avec les responsables de Nuxt et prévoyons de publier des utilitaires tiers similaires adaptés à leur écosystème dans un avenir proche.

Si l'un des tiers que vous utilisez dans votre application Next.js est compatible avec @next/third-parties, installez le package et testez-le. Nous aimerions connaître votre avis sur GitHub.