Drittanbieter-JavaScript optimieren

Drittanbieter-Scripts wirken sich auf die Leistung aus. Daher ist es wichtig, sie regelmäßig prüfen und effiziente Verfahren zum Laden zu verwenden. In diesem Codelab erfahren Sie, wie Sie das Laden von Drittanbieterressourcen optimieren. Folgende Techniken werden behandelt:

  • Laden des Skripts wird zurückgestellt

  • Lazy Loading von nicht kritischen Ressourcen

  • Vorverbindung zu erforderlichen Ursprüngen herstellen

Die enthaltene Beispielanwendung enthält eine einfache Webseite mit drei Funktionen aus Drittanbieterquellen:

  • Ein eingebettetes Video

  • Bibliothek zur Datenvisualisierung zum Rendern eines Liniendiagramms

  • Ein Social-Media-Widget zum Teilen

Screenshot der Seite, auf dem Ressourcen von Drittanbietern hervorgehoben sind.
Ressourcen von Drittanbietern in der Beispiel-App

Zuerst messen Sie die Leistung der App und wenden dann die einzelnen Verfahren an, um verschiedene Aspekte der App-Leistung zu verbessern.

Leistung messen

Öffnen Sie zuerst die Beispiel-App im Vollbildmodus:

  1. Klicke auf Zu bearbeitende Remixe, damit das Projekt bearbeitet werden kann.
  2. Um die Website als Vorschau anzusehen, wählen Sie App ansehen und dann Vollbild Vollbild aus.

Führen Sie auf der Seite eine Lighthouse-Leistungsprüfung durch, um die Basisleistung zu ermitteln:

  1. Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.
  2. Klicken Sie auf den Tab Lighthouse.
  3. Klicken Sie auf Mobil.
  4. Klicken Sie das Kästchen Leistung an. (Sie können die restlichen Kontrollkästchen im Bereich Audits deaktivieren.)
  5. Klicken Sie auf Simulated Fast 3G, 4x CPU Slowdown.
  6. Klicken Sie das Kästchen Speicherinhalt löschen an.
  7. Klicken Sie auf Audits ausführen.

Wenn Sie eine Prüfung auf Ihrem Computer durchführen, können die genauen Ergebnisse variieren. Sie sollten jedoch feststellen, dass die Zeit für First Contentful Paint (FCP) ziemlich hoch ist und Lighthouse zwei Möglichkeiten zur Untersuchung vorschlägt: Ressourcen entfernen, die das Rendering blockieren und Vorverbindung zu erforderlichen Ursprüngen herstellen. Auch wenn alle Messwerte grün sind, können Optimierungen dennoch zu einer Verbesserung führen.

Screenshot der Lighthouse-Prüfung mit einem FCP-Wert von 2,4 Sekunden und zwei Möglichkeiten: Ressourcen entfernen, die das Rendering blockieren, und Vorverbindung zu erforderlichen Ursprüngen herstellen.

Drittanbieter-JavaScript zurückstellen

Die Prüfung Ressourcen, die das Rendering blockieren, hat ergeben, dass Sie Zeit sparen können, indem Sie ein von d3js.org stammendes Skript aufschieben:

Screenshot der Prüfung „Ressourcen entfernen, die das Rendering blockieren“ mit hervorgehobenem Skript d3.v3.min.js.

D3.js ist eine JavaScript-Bibliothek zum Erstellen von Datenvisualisierungen. Die Datei script.js in der Beispiel-App verwendet D3-Dienstfunktionen, um das SVG-Liniendiagramm zu erstellen und an die Seite anzuhängen. Die Reihenfolge der Vorgänge ist hier wichtig: script.js muss ausgeführt werden, nachdem das Dokument geparst und die D3-Bibliothek geladen wurde. Deshalb wird es direkt vor dem schließenden </body>-Tag in index.html eingefügt.

Das D3-Skript ist jedoch im <head> der Seite enthalten, wodurch das Parsen des restlichen Dokuments blockiert wird:

Screenshot von index.html mit hervorgehobenem Script-Tag im Kopf

Zwei magische Attribute können die Blockierung des Parsers aufheben, wenn sie dem Skript-Tag hinzugefügt werden:

  • async sorgt dafür, dass Skripts im Hintergrund heruntergeladen und bei der ersten Gelegenheit nach Abschluss des Downloads ausgeführt werden.

  • Mit defer wird sichergestellt, dass die Skripts im Hintergrund heruntergeladen und nach dem Parsen ausgeführt werden.

Da dieses Diagramm für die gesamte Seite nicht wirklich entscheidend ist und höchstwahrscheinlich „below the fold“ (mit Scrollen sichtbar) platziert wird, verwenden Sie defer, um sicherzustellen, dass keine Parserblockierung auftreten.

Schritt 1: Skript asynchron mit dem Attribut defer laden

Fügen Sie in Zeile 17 in index.html das Attribut defer dem Element <script> hinzu:

<script src="https://d3js.org/d3.v3.min.js" defer></script>

Schritt 2: Korrekte Reihenfolge der Vorgänge sicherstellen

Jetzt, da D3 verzögert wird, wird script.js ausgeführt, bevor D3 bereit ist, was zu einem Fehler führt.

Skripts mit dem Attribut defer werden in der Reihenfolge ausgeführt, in der sie angegeben wurden. Damit script.js ausgeführt wird, nachdem D3 bereit ist, fügen Sie defer hinzu und verschieben Sie es bis zur <head> des Dokuments, direkt nach dem <script>-Element in D3. Der Parser wird jetzt nicht mehr blockiert und der Download wird früher gestartet.

<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>

Lazy Loading von Ressourcen von Drittanbietern

Alle Ressourcen, die sich „below the fold“ befinden, eignen sich gut für Lazy Loading.

Bei der Beispiel-App ist ein YouTube-Video in einem iframe eingebettet. So kannst du prüfen, wie viele Anfragen die Seite sendet und welche vom eingebetteten YouTube-iFrame stammen:

  1. Um die Website als Vorschau anzusehen, wählen Sie App ansehen und dann Vollbild Vollbild aus.
  2. Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.
  3. Klicken Sie auf den Tab Netzwerk.
  4. Klicken Sie das Kästchen Cache deaktivieren an.
  5. Wählen Sie im Drop-down-Menü Drosselung die Option Schnelles 3G aus.
  6. Lade die Seite neu.

Screenshot des Entwicklertools-Steuerfelds „Netzwerk“.

Im Bereich Netzwerk sehen Sie, dass die Seite insgesamt 28 Anfragen gestellt und fast 1 MB an komprimierten Ressourcen übertragen hat.

Um die Anfragen von YouTube-iframe zu identifizieren, suchen Sie in der Spalte Initiator nach der Video-ID 6lfaiXM6waw. So gruppieren Sie alle Anfragen nach Domain:

  • Klicken Sie im Bereich Netzwerk mit der rechten Maustaste auf einen Spaltentitel.

  • Wählen Sie im Drop-down-Menü die Spalte Domains aus.

  • Klicken Sie auf den Spaltentitel Domains, um die Anfragen nach Domain zu sortieren.

Die neue Sortierung zeigt, dass es zusätzliche Anfragen an Google-Domains gibt. Insgesamt sendet der YouTube-iFrame 14 Anfragen nach Skripts, Stylesheets, Bilder und Schriftarten. Aber sie benötigen nicht wirklich alle diese Assets, wenn sie nicht nach unten scrollen, um das Video abzuspielen.

Indem Sie mit dem Lazy Loading des Videos warten, bis der Nutzer zu diesem Abschnitt der Seite scrollt, verringern Sie die Anzahl der anfänglichen Anfragen. Dadurch werden die Daten der Nutzer eingespart und der anfängliche Ladevorgang beschleunigt.

Eine Möglichkeit, Lazy Loading zu implementieren, ist die Verwendung von Intersection Observer. Diese Browser-API benachrichtigt Sie, wenn ein Element in den Darstellungsbereich des Browsers eintritt oder diesen verlässt.

Schritt 1: Verhindern, dass das Video anfangs geladen wird

Wenn Sie das Lazy Loading des Video-iFrames verwenden möchten, müssen Sie zuerst verhindern, dass es wie gewohnt geladen wird. Ersetze dazu das Attribut src durch das Attribut data-src, um die Video-URL anzugeben:

<iframe width="560" height="315" data-src="https://www.youtube.com/embed/lS9D6w1GzGY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

data-src ist ein Datenattribut, mit dem Sie zusätzliche Informationen zu Standard-HTML-Elementen speichern können. Ein Datenattribut kann beliebig benannt werden, solange es mit „data-“ beginnt.

Ein iFrame ohne src wird einfach nicht geladen.

Schritt 2: Video mit Intersection Observer per Lazy Loading laden

Damit das Video geladen werden kann, wenn ein Nutzer zu ihm scrollt, müssen Sie wissen, wann das passiert. Hier kommt die Intersection Observer API ins Spiel. Mit der Intersection Observer API können Sie eine Callback-Funktion registrieren, die immer dann ausgeführt wird, wenn ein zu erfassendes Element den Darstellungsbereich erreicht oder verlässt.

Erstellen Sie zuerst eine neue Datei und nennen Sie sie lazy-load.js:

  • Klicken Sie auf Neue Datei und geben Sie einen Namen ein.
  • Klicken Sie auf Diese Datei hinzufügen.

Fügen Sie das Skript-Tag in den Dokumentkopf ein:

 <script src="/lazy-load.js" defer></script>

Erstellen Sie in lazy-load.js eine neue IntersectionObserver und übergeben Sie eine Callback-Funktion, die ausgeführt werden soll:

// create a new Intersection Observer
let observer = new IntersectionObserver(callback);

Weisen Sie observer nun ein Zielelement zu, das Sie sich ansehen möchten (in diesem Fall der Video-iFrame), indem Sie es als Argument in der Methode observe übergeben:

// the element that you want to watch
const element = document.querySelector('iframe');

// register the element with the observe method
observer.observe(element);

callback erhält eine Liste von IntersectionObserverEntry-Objekten und das IntersectionObserver-Objekt selbst. Jeder Eintrag enthält ein target-Element und Eigenschaften, die unter anderem seine Abmessungen, die Position und den Zeitpunkt beschreiben, zu dem der Darstellungsbereich betreten wurde. Eines der Eigenschaften von IntersectionObserverEntry ist isIntersecting. Das ist ein boolescher Wert, der gleich true ist, wenn das Element in den Darstellungsbereich gelangt.

In diesem Beispiel ist target der iframe. isIntersecting ist gleich true, wenn target in den Darstellungsbereich gelangt. Wenn Sie dies in Aktion sehen möchten, ersetzen Sie callback durch die folgende Funktion:

let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
    entries.forEach(entry => {
      console.log(entry.target);
      console.log(entry.isIntersecting);
    });
  });
  1. Um die Website als Vorschau anzusehen, wählen Sie App ansehen und dann Vollbild Vollbild aus.
  2. Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.
  3. Klicken Sie auf den Tab Console.

Scrolle nach oben und unten. Der Wert von isIntersecting sollte geändert werden und das Zielelement sollte in der Konsole protokolliert werden.

Wenn das Video geladen werden soll, wenn der Nutzer an seine Position scrollt, verwenden Sie isIntersecting als Bedingung, um eine loadElement-Funktion auszuführen. Diese ruft den Wert von data-src des iframe-Elements ab und legt ihn als src-Attribut des iframe-Elements fest. Dieser Austausch löst das Laden des Videos aus. Sobald das Video geladen ist, rufen Sie die unobserve-Methode für observer auf, um die Beobachtung des Zielelements zu beenden:

let observer = new IntersectionObserver(function (entries, observer) {
  entries.forEach(entry => {
    console.log(entry.target);
    console.log(entry.isIntersecting);
  });
});
    if (entry.isIntersecting) {
      // do this when the element enters the viewport
      loadElement(entry.target);
      // stop watching
      observer.unobserve(entry.target);
    }
  });
});

function loadElement(element) {
  const src = element.getAttribute('data-src');
  element.src = src;
}

Schritt 3: Leistung neu bewerten

Wenn Sie sehen möchten, wie sich Größe und Anzahl der Ressourcen geändert haben, öffnen Sie in den Entwicklertools den Bereich Netzwerk und aktualisieren Sie die Seite noch einmal. Im Steuerfeld Netzwerk ist zu sehen, dass die Seite 14 Anfragen und nur 260 KB groß ist. Das ist eine bedeutende Verbesserung!

Scrollen Sie auf der Seite nach unten und behalten Sie den Bereich Network im Auge. Wenn Sie das Video aufrufen, sollten Sie sehen, dass die Seite zusätzliche Anfragen auslöst.

Vorverbindung zu erforderlichen Ursprüngen herstellen

Du hast nicht kritisches JavaScript zurückgestellt und YouTube-Anfragen per Lazy Loading aufgeschoben. Jetzt ist es an der Zeit, die verbleibenden Drittanbieterinhalte zu optimieren.

Wenn Sie das Attribut rel=preconnect zu einem Link hinzufügen, wird der Browser angewiesen, eine Verbindung zu einer Domain herzustellen, bevor die Anfrage für diese Ressource gestellt wird. Dieses Attribut sollte am besten für Quellen verwendet werden, die Ressourcen bereitstellen, von denen Sie sicher sind, dass die Seite sie benötigt.

Bei der Lighthouse-Prüfung, die Sie im ersten Schritt durchgeführt haben, wurde unter Vorverbindung zu erforderlichen Ursprüngen vor verbinden vorgeschlagen, dass Sie etwa 400 ms sparen können, wenn Sie frühe Verbindungen zu staticxx.facebook.com und youtube.com herstellen:

Prüfung der Vorabverbindung zu erforderlichen Ursprüngen mit hervorgehobener Domain staticxx.facebook.com.

Da das YouTube-Video jetzt Lazy-Loading ist, bleibt nur staticxx.facebook.com übrig, die Quelle des Widgets zum Teilen von sozialen Medien. Um eine frühzeitige Verbindung zu dieser Domain herzustellen, ist es so einfach, ein <link>-Tag zum <head> des Dokuments hinzuzufügen:

  <link rel="preconnect" href="https://staticxx.facebook.com">

Leistung neu bewerten

So sieht der Status der Seite nach der Optimierung aus. Folgen Sie der Anleitung im Abschnitt Leistung messen des Codelab, um eine weitere Lighthouse-Prüfung durchzuführen.

Bei der Lighthouse-Prüfung wird ein FCP-Wert von 1 Sekunde und eine Leistungsbewertung von 99 ermittelt.