Ein Next.js-Paket zum Verwalten von Bibliotheken von Drittanbietern

2021 hat das Chrome Aurora-Team die Skriptkomponente eingeführt, um die Ladeleistung von Drittanbieter-Skripts in Next.js zu verbessern. Seit der Einführung haben wir die Funktionen erweitert, um das Laden von Drittanbieterressourcen für Entwickler einfacher und schneller zu machen.

Dieser Blogpost bietet einen Überblick über die neueren Funktionen, die wir veröffentlicht haben, insbesondere die Bibliothek @next/third-parties, sowie einen Überblick über zukünftige Initiativen in unserer Roadmap.

Auswirkungen von Drittanbieter-Skripts auf die Leistung

41% aller Anfragen von Drittanbietern auf Next.js-Websites sind Skripts. Im Gegensatz zu anderen Inhaltstypen kann das Herunterladen und Ausführen von Skripts viel Zeit in Anspruch nehmen, was das Rendering blockieren und die Interaktion der Nutzer verzögern kann. Daten aus dem Bericht zur Nutzererfahrung in Chrome (CrUX) zeigen, dass Next.js-Websites, die mehr Drittanbieter-Skripts laden, niedrigere Erfolgsquoten für Interaction to Next Paint (INP) und Largest Contentful Paint (LCP) haben.

Balkendiagramm, das den Rückgang der Next.js-Werte mit guten INP- und LCP-Werten im Verhältnis zur Anzahl der geladenen Drittanbieter zeigt
UX-Bericht für Chrome 2023 (110.823 Websites)

Die in diesem Diagramm beobachtete Korrelation deutet nicht auf eine Kausalität hin. Lokale Tests liefern jedoch zusätzliche Hinweise darauf, dass Skripts von Drittanbietern die Seitenleistung erheblich beeinträchtigen. In der folgenden Tabelle werden beispielsweise verschiedene Labs-Messwerte verglichen, wenn ein Google Tag Manager-Container mit 18 zufällig ausgewählten Tags zur Taxonomie, einer beliebten Beispiel-App für Next.js, hinzugefügt wird.

Balkendiagramm, das den Unterschied zwischen verschiedenen Lab-Messwerten zeigt, wenn eine Website mit und ohne Google Tag Manager geladen wird
WebPageTest (Mobile 4G – Virginia, USA)

In der WebPageTest-Dokumentation finden Sie Details zur Messung dieser Zeitangaben. Auf einen Blick sehen wir, dass alle diese Lab-Messwerte vom GTM-Container betroffen sind. Zum Beispiel konnte Total Blocking Time (TBT) – ein nützlicher Lab-Proxy, der sich annähernd INP ausmacht – einen Anstieg von fast 20-mal verzeichnen.

Skriptkomponente

Bei der Auslieferung der <Script>-Komponente in Next.js haben wir sie über eine nutzerfreundliche API eingeführt, die dem traditionellen <script>-Element sehr ähnlich ist. Damit können Entwickler in jeder Komponente ihrer Anwendung ein Drittanbieterskript gemeinsam speichern. Next.js übernimmt dann die Sequenzierung des Skripts, nachdem kritische Ressourcen geladen wurden.

<!-- 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" />

Zehntausende Next.js-Anwendungen, darunter beliebte Websites wie Patreon, Target und Notion, verwenden die Komponente <Script>. Trotz seiner Wirksamkeit haben einige Entwickler Bedenken in Bezug auf folgende Aspekte geäußert:

  • Wo die <Script>-Komponente in einer Next.js-App platziert werden und dabei die unterschiedlichen Installationsanweisungen der verschiedenen Drittanbieter beachtet werden sollten (für Entwickler)
  • Welche Ladestrategie eignet sich am besten für verschiedene Drittanbieter-Skripts (Nutzerfreundlichkeit)?

Aus diesem Grund haben wir @next/third-parties eingeführt – eine spezialisierte Bibliothek, die eine Reihe optimierter Komponenten und Dienstprogramme bietet, die auf beliebte Drittanbieter zugeschnitten sind.

Für Entwickler: Bibliotheken von Drittanbietern einfacher verwalten

Viele Drittanbieter-Skripts werden auf einem erheblichen Prozentsatz der Next.js-Websites verwendet. Google Tag Manager ist dabei das beliebteste und wird von 66% der Websites genutzt. @next/third-parties baut auf der Komponente <Script> auf und führt übergeordnete Wrapper ein, die die Verwendung für diese gängigen Anwendungsfälle vereinfachen sollen.

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, ein weiteres weit verbreitetes Drittanbieter-Script (52% der Next.js-Websites), hat ebenfalls eine eigene Komponente.

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 vereinfacht das Laden häufig verwendeter Skripts, erweitert aber auch die Fähigkeit, Dienstprogramme für andere Drittanbieterkategorien wie Einbettungen zu entwickeln. So werden beispielsweise Google Maps- und YouTube-Einbettungen auf 8% bzw. 4% der Next.js-Websites verwendet. Außerdem haben wir Komponenten bereitgestellt, um das Laden zu vereinfachen.

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" />
    </>
  );
}

Nutzererfahrung: Bibliotheken von Drittanbietern schneller laden

In einer perfekten Welt wäre jede weit verbreitete Bibliothek von Drittanbietern vollständig optimiert, sodass Abstraktionen zur Leistungsverbesserung überflüssig wären. Bis dies jedoch Realität wird, können wir versuchen, die Nutzererfahrung durch die Integration über beliebte Frameworks wie Next.js zu verbessern. Wir können mit verschiedenen Ladetechniken experimentieren, dafür sorgen, dass Skripts in der richtigen Reihenfolge angeordnet sind, und unser Feedback letztendlich mit Drittanbietern teilen, um Upstream-Änderungen zu fördern.

Nehmen wir zum Beispiel YouTube-Einbettungen. Es gibt alternative Implementierungen, die eine wesentlich bessere Leistung als native Einbettungen haben. Derzeit wird für die von @next/third-parties exportierte <YouTubeEmbed>-Komponente lite-youtube-embed verwendet, was bei Next.js-Vergleich mit „Hello, World“ deutlich schneller geladen wird.

GIF, das den Vergleich des Seitenaufbaus zwischen der Komponente „Einbetten von YouTube“ und einem normalen YouTube-iFrame zeigt
WebPageTest (Mobile 4G – Virginia, USA)

Für Google Maps fügen wir loading="lazy" als Standardattribut für die Einbettung hinzu, damit die Karte nur dann geladen wird, wenn sie eine bestimmte Entfernung vom Darstellungsbereich entfernt ist. Es mag offensichtlich erscheinen, dass dieses Attribut einbezogen werden sollte – vor allem, da es in der Google Maps-Dokumentation im Beispielcode-Snippet enthalten ist. Aber nur 45% der Next.js-Websites, auf denen Google Maps eingebettet ist, verwenden loading="lazy".

Drittanbieterskripts in einem Web Worker ausführen

Ein fortgeschrittenes Verfahren, das wir in @next/third-parties untersuchen, besteht darin, die Übertragung von Drittanbieter-Skripts auf einen Web Worker zu vereinfachen. Da Bibliotheken wie Partytown von Bibliotheken genutzt werden, kann dies die Auswirkungen von Drittanbieterskripts auf die Seitenleistung erheblich reduzieren, da sie vollständig aus dem Hauptthread entfernt werden.

Das folgende animierte GIF zeigt die unterschiedlichen langen Aufgaben und die Blockierungszeit des Hauptthreads, wenn verschiedene <Script>-Strategien auf einen GTM-Container innerhalb einer Next.js-Website angewendet werden. Durch den Wechsel zwischen Strategieoptionen wird zwar die Ausführung dieser Skripts nur verzögert, doch durch die Verlagerung auf einen Web-Worker geht die Zeit im Hauptthread vollständig weg.

GIF, das die Unterschiede bei der Blockierungszeit des Hauptthreads bei den verschiedenen Skriptstrategien zeigt
WebPageTest (Mobile 4G – Virginia, USA)

In diesem Beispiel wurde durch das Verschieben der Ausführung des GTM-Containers und der zugehörigen Tag-Skripts zu einem Web Worker die TBT um 92%reduziert.

Bei nicht sorgfältiger Verwaltung kann diese Technik viele Drittanbieter-Skripts im Hintergrund zerstören, was die Fehlerbehebung schwierig macht. In den kommenden Monaten prüfen wir, ob die von @next/third-parties angebotenen Drittanbieterkomponenten bei der Ausführung in einem Web Worker ordnungsgemäß funktionieren. Falls ja, werden wir versuchen, Entwicklern eine einfache und optionale Möglichkeit zur Verfügung zu stellen, dieses Verfahren zu nutzen.

Nächste Schritte

Bei der Entwicklung dieses Pakets wurde deutlich, dass eine Zentralisierung der Ladeempfehlungen von Drittanbietern erforderlich war, damit auch andere Frameworks von denselben zugrunde liegenden Techniken profitieren konnten. Dies brachte uns darauf, Drittanbieterkapital zu entwickeln, eine Bibliothek, die JSON verwendet, um Ladetechniken von Drittanbietern zu beschreiben und derzeit als Grundlage für @next/third-parties zu dienen.

Bei den nächsten Schritten konzentrieren wir uns weiterhin darauf, die für Next.js bereitgestellten Komponenten zu verbessern, und bauen unsere Bemühungen auf ähnliche Dienstprogramme in anderen beliebten Frameworks und CMS-Plattformen aus. Wir arbeiten derzeit mit Nuxt-Wartungsunternehmen zusammen und planen, in naher Zukunft ähnliche Drittanbieter-Dienstprogramme herauszubringen, die auf ihr System zugeschnitten sind.

Wenn einer der Drittanbieter, die Sie in Ihrer Next.js-App verwenden, von @next/third-parties unterstützt wird, installieren Sie das Paket und probieren Sie es aus. Wir freuen uns auf Ihr Feedback auf GitHub.