Laden von Drittanbieterskripts in Next.js optimieren

Hier erfahren Sie mehr über die Script-Komponente von Next.js, die eine integrierte Lösung zum Optimieren des Ladens von Drittanbieter-Scripts bietet.

Leena Sohoni
Leena Sohoni

Etwa 45% der Anfragen von Websites, die über Mobilgeräte und Computer ausgeliefert werden, sind Drittanbieteranfragen, von denen 33% Scripts sind. Größe, Latenz und Laden von Drittanbieter-Scripts können sich erheblich auf die Leistung einer Website auswirken. Die Next.js-Skriptkomponente verfügt über integrierte Best Practices und Standardeinstellungen, die Entwickler dabei unterstützen, Drittanbieter-Skripts in ihre Anwendungen zu integrieren und gleichzeitig potenzielle Leistungsprobleme zu beheben.

Drittanbieter-Scripts und ihre Auswirkungen auf die Leistung

Mit Drittanbieter-Scripts können Webentwickler vorhandene Lösungen nutzen, um gängige Funktionen zu implementieren und die Entwicklungszeit zu verkürzen. Die Ersteller dieser Scripts haben jedoch in der Regel keinen Anreiz, die Leistungsauswirkungen auf die Website zu berücksichtigen, auf der sie ausgeführt werden. Diese Scripts sind auch für die Entwickler, die sie verwenden, eine Blackbox.

Scripts sind für einen erheblichen Teil der Drittanbieter-Byte verantwortlich, die von Websites aus verschiedenen Kategorien von Drittanbieteranfragen heruntergeladen werden. Standardmäßig priorisiert der Browser Scripts basierend auf ihrer Position im Dokument. Dies kann die Erkennung oder Ausführung von Scripts verzögern, die für die Nutzerfreundlichkeit entscheidend sind.

Für das Layout erforderliche Drittanbieterbibliotheken sollten frühzeitig geladen werden, damit die Seite gerendert werden kann. Drittanbieter, die für das erste Rendering nicht erforderlich sind, sollten verschoben werden, damit sie keine andere Verarbeitung im Hauptthread blockieren. Lighthouse bietet zwei Prüfungen, mit denen Scripts gekennzeichnet werden, die das Rendern oder den Haupt-Thread blockieren.

Lighthouse-Prüfungen für „Ressourcen entfernen, die das Rendering blockieren“ und „Drittanbieternutzung minimieren“

Es ist wichtig, die Reihenfolge des Ladens Ihrer Seite zu berücksichtigen, damit kritische Ressourcen nicht verzögert werden und nicht kritische Ressourcen keine kritischen Ressourcen blockieren.

Es gibt zwar Best Practices, mit denen sich die Auswirkungen von Drittanbietern minimieren lassen, aber möglicherweise wissen nicht alle, wie sie für jeden verwendeten Drittanbieter implementiert werden können. Das kann kompliziert sein, weil:

  • Im Durchschnitt nutzen Websites 21 bis 23 verschiedene Drittanbieter – einschließlich Scripts – auf Mobilgeräten und Computern. Die Verwendung und Empfehlungen können für jedes Gerät unterschiedlich sein.
  • Die Implementierung vieler Drittanbieter hängt davon ab, ob ein bestimmtes Framework oder eine Benutzeroberflächenbibliothek verwendet wird.
  • Neuere Bibliotheken von Drittanbietern werden häufig eingeführt.
  • Unterschiedliche geschäftliche Anforderungen im Zusammenhang mit demselben Drittanbieter erschweren es Entwicklern, die Verwendung zu standardisieren.

Aurora konzentriert sich auf Skripts von Drittanbietern

Im Rahmen der Zusammenarbeit von Aurora mit Open-Source-Web-Frameworks und ‑Tools werden solide Standardeinstellungen und Tools zur Verfügung gestellt, mit denen Entwickler Aspekte der Nutzerfreundlichkeit wie Leistung, Barrierefreiheit, Sicherheit und Mobilität verbessern können. 2021 haben wir uns darauf konzentriert, Framework-Stacks dabei zu helfen, die Nutzerfreundlichkeit und die Core Web Vitals-Messwerte zu verbessern.

Einer der wichtigsten Schritte, um unser Ziel zur Verbesserung der Framework-Leistung zu erreichen, war die Untersuchung der idealen Ladesequenz von Drittanbieter-Skripts in Next.js. Frameworks wie Next.js eignen sich hervorragend dazu, nützliche Standardeinstellungen und Funktionen bereitzustellen, mit denen Entwickler Ressourcen, einschließlich Drittanbieter, effizient laden können. Wir haben umfangreiche HTTP Archive- und Lighthouse-Daten ausgewertet, um herauszufinden, welche Drittanbieter das Rendering in verschiedenen Frameworks am häufigsten blockieren.

Um das Problem zu beheben, dass Drittanbieter-Scripts, die in einer Anwendung verwendet werden, im Haupt-Thread blockiert werden, haben wir die Script-Komponente entwickelt. Die Komponente umschließt Sequenzierungsfunktionen, um Entwicklern bessere Steuerelemente für das Laden von Drittanbieter-Scripts zur Verfügung zu stellen.

Drittanbieter-Scripts ohne Framework-Komponente sequenzieren

In der verfügbaren Anleitung zum Minimieren der Auswirkungen von renderblockierenden Scripts werden die folgenden Methoden zum effizienten Laden und Sequenzieren von Drittanbieter-Scripts beschrieben:

  1. Verwenden Sie das Attribut async oder defer mit <script>-Tags, die dem Browser mitteilen, nicht kritische Drittanbieter-Scripts zu laden, ohne den Dokumentparser zu blockieren. Scripts, die nicht für das erste Laden der Seite oder die erste Nutzerinteraktion erforderlich sind, können als nicht kritisch eingestuft werden.

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. Stellen Sie frühe Verbindungen zu erforderlichen Ursprüngen mithilfe von preconnect und dns-prefetch her. So kann der Download kritischer Scripts früher gestartet werden.

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. Lazy-load Ressourcen und Einbettungen von Drittanbietern, nachdem der Inhalt der Hauptseite geladen wurde oder der Nutzer zu dem Teil der Seite scrollt, in dem sie enthalten sind.

Next.js-Skriptkomponente

Die Next.js-Script-Komponente implementiert die oben genannten Methoden zur Sequenzierung von Scripts und bietet Entwicklern eine Vorlage, um ihre Ladestrategie zu definieren. Sobald die geeignete Strategie festgelegt wurde, wird sie optimal geladen, ohne andere kritische Ressourcen zu blockieren.

Die Script-Komponente basiert auf dem HTML-Tag <script> und bietet die Möglichkeit, die Ladepriorität für Drittanbieter-Scripts mithilfe des Attributs „strategy“ festzulegen.

// Example for beforeInteractive:
<Script src="https://cdnjs.cloudflare.com/polyfill/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" />

Das Attribut „Strategie“ kann drei Werte annehmen.

  1. beforeInteractive: Diese Option kann für wichtige Skripts verwendet werden, die ausgeführt werden sollten, bevor die Seite interaktiv wird. Next.js sorgt dafür, dass solche Scripts in die anfängliche HTML-Datei auf dem Server eingefügt und vor anderen selbst gebundelten JavaScript-Scripts ausgeführt werden. Einwilligungsverwaltung, Scripts zur Boterkennung oder Hilfsbibliotheken, die zum Rendern kritischer Inhalte erforderlich sind, sind gute Kandidaten für diese Strategie.

  2. afterInteractive: Dies ist die Standardstrategie. Sie entspricht dem Laden eines Scripts mit dem Attribut „defer“. Sie sollte für Scripts verwendet werden, die der Browser ausführen kann, nachdem die Seite interaktiv geworden ist, z. B. Analysescripts. Next.js fügt diese Skripts clientseitig ein und sie werden ausgeführt, nachdem die Seite vollständig geladen wurde. Sofern nicht anders angegeben, werden daher alle Drittanbieterskripte, die mithilfe der Skriptkomponente definiert werden, von Next.js zurückgestellt, wodurch ein starker Standardwert bereitgestellt wird.

  3. lazyOnload: Mit dieser Option können Scripts mit niedriger Priorität im Lazy-Load-Verfahren geladen werden, wenn der Browser inaktiv ist. Die Funktionen solcher Scripts sind nicht sofort nach der Interaktivität der Seite erforderlich, z. B. Chat- oder Social-Media-Plug-ins.

Entwickler können Next.js darüber informieren, wie ihre Anwendung ein Skript verwendet, indem sie die Strategie angeben. So kann das Framework Optimierungen und Best Practices für das Laden des Scripts anwenden und gleichzeitig die beste Ladeabfolge sicherstellen.

Mit der Script-Komponente können Entwickler Drittanbieter-Skripts für spät geladene Drittanbieter an einer beliebigen Stelle in der Anwendung und für kritische Scripts auf Dokumentebene platzieren. Das bedeutet, dass die Script-Komponente sich an derselben Stelle wie die Komponente befinden kann, die das Script verwendet. Nach der Hydratisierung wird das Script je nach verwendeter Strategie in den Kopf des ursprünglich gerenderten Dokuments oder unten in den Textkörper eingefügt.

Wirkung messen

Wir haben die Vorlagen für die Next.js-Commerce-App und den Starter-Blog verwendet, um zwei Demo-Apps zu erstellen, mit denen sich die Auswirkungen der Einbindung von Drittanbieter-Scripts messen lassen. Gängige Drittanbieter für Google Tag Manager und Einbettungen in sozialen Medien wurden zuerst direkt auf den Seiten dieser Apps und dann über die Script-Komponente eingebunden. Anschließend haben wir die Leistung dieser Seiten mit WebPageTest verglichen.

Drittanbieter-Skripts in einer Next.js-Commerce-App

Der Vorlage für die Handels-App wurden für die Demo wie unten angegeben Drittanbieter-Scripts hinzugefügt.

Vorher Nachher
Google Tag Manager mit asynchroner Ausführung Skript-Komponente mit Strategie = afterInteractive für beide Skripts
Schaltfläche „Folgen“ auf Twitter ohne asynchrone oder verzögerte Ausführung
Konfiguration von Script und Scriptkomponente für Demo 1 mit 2 Scripts

Im folgenden Vergleich ist der visuelle Fortschritt für beide Versionen des Next.js-Commerce-Starter-Kits zu sehen. Wie Sie sehen, tritt der LCP fast eine Sekunde früher auf, wenn die Skriptkomponente mit der richtigen Ladestrategie aktiviert ist.

Filmstreifenvergleich mit Verbesserung des LCP

Drittanbieter-Scripts in einem Next.js-Blog

Drittanbieter-Skripts wurden der Demo-Blog-App wie unten dargestellt hinzugefügt.

Vorher Nachher
Google Tag Manager mit asynchroner Ausführung Script-Komponente mit „strategy“ = „lazyonload“ für jedes der vier Scripts
Schaltfläche „Twitter folgen“ mit asynchroner Ausführung
YouTube-Schaltfläche „Abonnieren“ ohne asynchrone oder verzögerte Auslieferung
LinkedIn Folgen-Schaltfläche ohne asynchron oder verzögert
Konfiguration von Script und Scriptkomponente für Demo 2 mit 4 Scripts
Video, das den Ladefortschritt für die Indexseite mit und ohne Skriptkomponente zeigt. Mit der Script-Komponente konnte eine Verbesserung des FCP um 0,5 Sekunden erzielt werden.

Wie im Video zu sehen, dauert der First Contentful Paint (FCP) auf der Seite ohne Script-Komponente 0,9 Sekunden und mit Script-Komponente 0,4 Sekunden.

Nächste Schritte für die Skriptkomponente

Die Strategieoptionen für afterInteractive und lazyOnload bieten zwar eine erhebliche Kontrolle über renderblockierende Scripts, wir prüfen aber auch andere Optionen, die die Nutzbarkeit der Script-Komponente erhöhen würden.

Web-Worker verwenden

Mit Webworkern können unabhängige Scripts in Hintergrundthreads ausgeführt werden, wodurch der Hauptthread freigegeben wird, um Aufgaben der Benutzeroberfläche zu verarbeiten und die Leistung zu verbessern. Webworker eignen sich am besten, um die JavaScript-Verarbeitung statt der UI-Arbeit vom Haupt-Thread auszulagern. Für den Kundensupport oder das Marketing verwendete Skripts, die normalerweise nicht mit der Benutzeroberfläche interagieren, eignen sich gut für die Ausführung in einem Hintergrundthread. Mit der schlanken Drittanbieterbibliothek PartyTown können Sie solche Scripts in einem Webworker isolieren.

Bei der aktuellen Implementierung der Next.js-Scriptkomponente empfehlen wir, diese Scripts im Hauptthread zu verschieben, indem Sie die Strategie auf afterInteractive oder lazyOnload festlegen. Künftig möchten wir die Strategieoption 'worker' einführen, mit der Next.js PartyTown oder eine benutzerdefinierte Lösung verwenden kann, um Scripts in Webworkern auszuführen. Wir freuen uns über Feedback von Entwicklern zu diesem RFC.

CLS minimieren

Eingebettete Inhalte von Drittanbietern wie Anzeigen, Videos oder Social-Media-Feeds können beim Lazy-Loading zu Layoutverschiebungen führen. Das wirkt sich auf die Nutzerfreundlichkeit und den Messwert Cumulative Layout Shift (CLS) für die Seite aus. Sie können den CLS minimieren, indem Sie die Größe des Containers angeben, in dem das eingebettete Element geladen wird.

Mit der Script-Komponente können eingebettete Inhalte geladen werden, die zu Layoutverschiebungen führen können. Wir überlegen, sie um Konfigurationsoptionen zu ergänzen, mit denen sich der CLS reduzieren lässt. Diese kann innerhalb der Skript-Komponente selbst oder als Companion-Komponente zur Verfügung gestellt werden.

Wrapper-Komponenten

Die Syntax und die Ladestrategie für das Einbinden beliebter Drittanbieter-Skripts wie Google Analytics oder Google Tag Manager (GTM) sind in der Regel festgelegt. Diese können für jeden Scripttyp in einzelnen Wrapper-Komponenten gekapselt werden. Entwicklern stehen nur wenige anwendungsspezifische Attribute wie die Tracking-ID zur Verfügung. Wrapper-Komponenten bieten Entwicklern folgende Vorteile:

  1. So können sie beliebte Script-Tags einfacher einbinden.
  2. Das Framework verwendet die optimale Strategie.

Fazit

Scripts von Drittanbietern werden in der Regel erstellt, um bestimmte Funktionen in die nutzende Website einzubinden. Um die Auswirkungen nicht kritischer Scripts zu verringern, empfehlen wir, sie zu verschieben. Das geschieht bei der Next.js-Script-Komponente standardmäßig. Entwickler können sich darauf verlassen, dass enthaltene Scripts keine kritischen Funktionen verzögern, es sei denn, sie wenden ausdrücklich die beforeInteractive-Strategie an. Ähnlich wie bei der Next.js-Script-Komponente können Framework-Entwickler diese Funktionen auch in anderen Frameworks implementieren. Wir erwägen derzeit, mit dem Nuxt.js-Team eine ähnliche Komponente zu entwickeln. Basierend auf dem Feedback hoffen wir auch, die Script-Komponente weiter zu verbessern, um weitere Anwendungsfälle abzudecken.

Danksagung

Vielen Dank an Kara Erickson, Janicklas Ralph, Katie Hempenius, Philip Walton, Jeremy Wagner und Addy Osmani für ihr Feedback zu diesem Beitrag.