Drittanbieter-JavaScript optimieren

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

  • Laden des Skripts verzögern

  • Lazy Loading für nicht kritische Ressourcen

  • Vorverbindung zu erforderlichen Ursprüngen herstellen

Die enthaltene Beispiel-App enthält eine einfache Webseite mit drei Funktionen aus externen Quellen:

  • Eine Videoeinbettung

  • Eine Datenvisualisierungsbibliothek zum Rendern eines Liniendiagramms

  • Ein Widget zum Teilen in sozialen Medien

<ph type="x-smartling-placeholder">
</ph> Screenshot der Seite mit hervorgehobenen Ressourcen von Drittanbietern
Ressourcen von Drittanbietern in der Beispiel-App.

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

Leistung messen

Öffnen Sie zuerst die Beispiel-App im Vollbildmodus:

  1. Klicke auf Zum Bearbeiten Remix, damit das Projekt bearbeitet werden kann.
  2. Wenn Sie sich eine Vorschau der Website ansehen möchten, klicken Sie auf App ansehen. Drücken Sie dann Vollbild Vollbild

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

  1. Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Option + J“ auf einem 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 Simuliertes schnelles 3G, 4-fache CPU-Verlangsamung.
  6. Aktivieren Sie das Kontrollkästchen Speicherinhalt löschen.
  7. Klicken Sie auf Audits ausführen.

Wenn Sie einen Audit auf Ihrem Computer ausführen, können die genauen Ergebnisse variieren. Sie sollten jedoch feststellen, dass die Zeit für First Contentful Paint (FCP) ziemlich hoch ist und dass Lighthouse zwei Möglichkeiten zur Untersuchung vorschlägt: Ressourcen entfernen, die das Rendering blockieren und Vorabverbindung mit erforderlichen Quellen herstellen. Auch wenn alle Messwerte im grünen Bereich sind, führen Optimierungen zu Verbesserungen.

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

Drittanbieter-JavaScript aussetzen

Bei der Prüfung Eliminieren Sie Ressourcen, die das Rendering blockieren, haben Sie festgestellt, dass Sie Zeit sparen können, indem Sie ein Script von d3js.org verschieben:

Screenshot: Prüfung „Eliminieren Sie die Prüfung von Ressourcen, die das Rendering blockieren“, mit hervorgehobenem Script „d3.v3.min.js“

D3.js ist eine JavaScript-Bibliothek zum Erstellen von Datenvisualisierungen. Die Datei script.js in der Beispiel-App verwendet D3-Dienstprogrammfunktionen, 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 steht es direkt vor dem schließenden </body>-Tag in index.html.

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 Header

Mit zwei magischen Attributen kann die Blockierung des Parsers aufgehoben werden, wenn sie dem Skript-Tag hinzugefügt werden:

  • Mit async wird sichergestellt, dass Skripts im Hintergrund heruntergeladen und beim ersten Mal nach dem Download ausgeführt werden.

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

Da dieses Diagramm für die Gesamtseite nicht wirklich entscheidend ist und sich höchstwahrscheinlich „below the fold“ befindet, sollte defer verwendet werden, damit der Parser nicht blockiert wird.

Schritt 1: Skript asynchron mit dem Attribut defer laden

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

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

Schritt 2: Die richtige Reihenfolge der Vorgänge sicherstellen

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

Skripts mit dem Attribut defer werden in der angegebenen Reihenfolge ausgeführt. Damit script.js ausgeführt wird, nachdem D3 bereit ist, fügen Sie defer hinzu und verschieben Sie es in den Bereich <head> des Dokuments, direkt nach dem D3-Element <script>. Jetzt wird der Parser nicht mehr blockiert und der Download beginnt früher.

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

Lazy Loading von Drittanbieterressourcen

Alle Ressourcen, die ohne Scrollen sichtbar sind, eignen sich gut für das Lazy Loading.

In der Beispiel-App ist ein YouTube-Video in einen iFrame eingebettet. So kannst du überprüfen, wie viele Anfragen die Seite stellt und welche vom eingebetteten YouTube-iFrame kommen:

  1. Wenn Sie sich eine Vorschau der Website ansehen möchten, klicken Sie auf App ansehen. Drücken Sie dann Vollbild Vollbild
  2. Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Option + J“ auf einem 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-Bereichs „Network“.

Im Steuerfeld Netzwerk ist zu sehen, dass die Seite insgesamt 28 Anfragen gesendet und fast 1 MB an komprimierten Ressourcen übertragen hat.

Suchen Sie in der Spalte Initiator nach der Video-ID 6lfaiXM6waw, um die vom YouTube-iframe gesendeten Anfragen zu identifizieren. 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 werden über den YouTube-iFrame 14 Anfragen für Skripts, Stylesheets, Bilder und Schriftarten gestellt. Aber wenn Nutzer nicht nach unten scrollen, um sich das Video anzusehen, werden nicht alle diese Assets benötigt.

Wenn Sie mit dem Lazy Loading für das Video warten, bis ein Nutzer nach unten zu diesem Abschnitt der Seite scrollt, verringern Sie die Anzahl der Anfragen, die von der Seite anfänglich gestellt werden. Dieser Ansatz erspart den Nutzenden und beschleunigt den anfänglichen Ladevorgang.

Eine Möglichkeit zum Implementieren von Lazy Loading ist die Verwendung von Intersection Observer. Diese Browser-API benachrichtigt Sie, wenn ein Element den Darstellungsbereich des Browsers erreicht oder verlässt.

Schritt 1: Verhindern, dass das Video zuerst geladen wird

Für das Lazy Loading des Video-iFrames müssen Sie zuerst verhindern, dass er wie gewohnt geladen wird. Ersetze dazu das Attribut src durch das Attribut data-src, mit dem die Video-URL angegeben wird:

<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: Intersection Observer verwenden, um das Video per Lazy Loading zu laden

Damit das Video geladen wird, wenn ein Nutzer zu dem Video scrollt, müssen Sie wissen, wann dies geschieht. Hier kommt die Intersection Observer API ins Spiel. Mit der Intersection Observer API können Sie eine Callback-Funktion registrieren, die ausgeführt wird, wenn ein zu verfolgendes Element den Darstellungsbereich betritt 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 zur Wiedergabe zu (in diesem Fall den Video-iFrame), indem Sie es als Argument in der observe-Methode ü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 mit IntersectionObserverEntry-Objekten und das IntersectionObserver-Objekt selbst. Jeder Eintrag enthält ein target-Element und Eigenschaften, die u. a. seine Abmessungen, seine Position und den Zeitpunkt des Eintritts in den Darstellungsbereich enthalten. Eine der Eigenschaften von IntersectionObserverEntry ist isIntersecting – ein boolescher Wert, der gleich true ist, wenn das Element in den Darstellungsbereich gelangt.

In diesem Beispiel ist target die iframe. isIntersecting entspricht true, wenn target in den Darstellungsbereich gelangt. Ersetzen Sie callback durch die folgende Funktion, um dies in Aktion zu sehen:

let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
    entries.forEach(entry => {
      console.log(entry.target);
      console.log(entry.isIntersecting);
    });
  });
  1. Wenn Sie sich eine Vorschau der Website ansehen möchten, klicken Sie auf App ansehen. Drücken Sie dann Vollbild Vollbild
  2. Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Option + J“ auf einem Mac), um die Entwicklertools zu öffnen.
  3. Klicken Sie auf den Tab Console.

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

Soll das Video geladen werden, wenn der Nutzer zu seiner Position scrollt, verwenden Sie isIntersecting als Bedingung, um eine loadElement-Funktion auszuführen. Diese ruft den Wert aus dem data-src des iframe-Elements ab und legt ihn als src-Attribut des iframe-Elements fest. Dadurch wird das Laden des Videos ausgelöst. Sobald das Video geladen ist, kannst du die unobserve-Methode für observer aufrufen, 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 gesendet hat. Das ist eine bedeutende Verbesserung!

Scrollen Sie auf der Seite nach unten und behalten Sie den Bereich Netzwerk 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 ausgesetzt und die YouTube-Anfragen per Lazy Loading geladen. Nun ist es an der Zeit, die verbleibenden Drittanbieterinhalte zu optimieren.

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

Die Lighthouse-Prüfung, die Sie im ersten Schritt durchgeführt haben, wurde unter Vorabverbindung mit erforderlichen Ursprüngen herstellen vorgeschlagen, bei dem Sie etwa 400 ms sparen können, wenn Sie frühzeitige Verbindungen zu staticxx.facebook.com und youtube.com herstellen:

Stellen Sie eine Vorverbindung zur erforderlichen Ursprungsprüfung her, wobei die Domain staticxx.facebook.com hervorgehoben ist.

Da das YouTube-Video nun Lazy-Loading ist, bleibt nur staticxx.facebook.com zurück, die Quelle des Social-Media-Widgets zum Teilen. Um eine frühe Verbindung zu dieser Domain herzustellen, müssen Sie nur ein <link>-Tag zum <head> des Dokuments hinzufügen:

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

Leistung neu bewerten

Hier sehen Sie den Status der Seite nach der Optimierung. Führen Sie die Schritte im Abschnitt Leistung messen des Codelabs aus, um einen weiteren Lighthouse-Audit durchzuführen.

Lighthouse-Audit ergab einen FCP-Wert von 1 Sekunde und eine Leistungsbewertung von 99.