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 pour faciliter et accélérer le chargement de 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-partys, et présente les futures initiatives de notre feuille de route.

Implications des scripts tiers sur les performances

41% de toutes les 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 sur l'expérience utilisateur Chrome (CrUX) montrent que les sites Next.js qui chargent plus de scripts tiers ont des taux de réussite inférieurs pour Interaction to Next Paint (INP) et Largest Contentful Paint (LCP).

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é. Toutefois, les tests locaux 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 illustrant la différence entre 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), un proxy d'atelier utile qui se rapproche de l'INP, a été multiplié par 20.

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. En l'utilisant, les développeurs peuvent colocaliser un script tiers dans n'importe quel composant de leur application, et Next.js se charge 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 :

  • Emplacement du 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 parfait, toutes les bibliothèques tierces largement adoptées seraient entièrement optimisées, ce qui rendrait inutile toute abstraction qui améliore leurs 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 de la bonne manière et, au final, partager nos commentaires avec les fournisseurs tiers pour encourager les modifications en amont.

Prenons l'exemple des intégrations YouTube. 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 un iFrame YouTube standard
WebPageTest (Mobile 4G - Virginia USA)

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. Il peut sembler évident d'inclure cet attribut, en particulier étant donné que la documentation Google Maps l'inclut dans son exemple d'extrait de code, mais seuls 45% des sites Next.js qui intègrent Google Maps utilisent loading="lazy".

Exécuter des scripts tiers dans un nœud de travail 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, bien que le passage d'une option de stratégie à une autre ne retarde que le moment où ces scripts s'exécutent, les déplacer vers un worker Web élimine complètement leur temps 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 particulier, le transfert de l'exécution du conteneur GTM et de ses scripts de balise associés vers un nœud de calcul Web a réduit le TBT 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. Cela nous a amenés à créer Third Party Capital, une bibliothèque qui utilise JSON pour décrire les techniques de chargement tierces, et 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.