Drittanbieter-Scripts beeinträchtigen die Leistung. Daher ist es wichtig, sie regelmäßig zu prüfen und effiziente Lademethoden zu verwenden. In diesem Codelab erfahren Sie, wie Sie das Laden von Drittanbieterressourcen optimieren. Dabei werden die folgenden Techniken behandelt:
Laden von Scripts verschieben
Nicht kritische Ressourcen per Lazy Loading laden
Vorabverbindung zu erforderlichen Quellen herstellen
Die enthaltene Beispiel-App enthält eine einfache Webseite mit drei Funktionen von Drittanbietern:
Ein eingebettetes Video
Eine Datenvisualisierungsbibliothek zum Rendern eines Liniendiagramms
Ein Widget zum Teilen in sozialen Medien
Sie beginnen damit, die Leistung der App zu messen, und wenden dann die einzelnen Techniken an, um verschiedene Aspekte der App-Leistung zu verbessern.
Leistung messen
Öffnen Sie zuerst die Beispiel-App im Vollbildmodus:
- Klicke auf Remix zum Bearbeiten, um das Projekt bearbeitbar zu machen.
- Wenn Sie sich eine Vorschau der Website ansehen möchten, drücken Sie App ansehen und dann Vollbild .
Führen Sie eine Lighthouse-Leistungsprüfung auf der Seite durch, um die Ausgangsleistung zu ermitteln:
- Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Option + J“ auf einem Mac), um die Entwicklertools zu öffnen.
- Klicken Sie auf den Tab Lighthouse.
- Klicken Sie auf Mobil.
- Klicken Sie das Kästchen Leistung an. Sie können die restlichen Kästchen im Bereich „Audits“ deaktivieren.
- Klicken Sie auf Simuliertes schnelles 3G, 4-fache CPU-Verlangsamung.
- Klicken Sie das Kästchen Speicherplatz freigeben an.
- Klicken Sie auf Analysen ausführen.
Wenn Sie eine Analyse auf Ihrem Computer ausführen, können die genauen Ergebnisse variieren. Sie sollten jedoch feststellen, dass die First Contentful Paint (FCP)-Zeit ziemlich hoch ist und dass Lighthouse zwei Möglichkeiten zur Untersuchung vorschlägt: Renderblockierende Ressourcen entfernen und Vorabverbindung zu erforderlichen Ursprüngen herstellen. Auch wenn alle Messwerte grün sind, können Optimierungen zu Verbesserungen führen.
JavaScript von Drittanbietern verzögern
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:
D3.js ist eine JavaScript-Bibliothek zum Erstellen von Datenvisualisierungen. In der Datei script.js
der Beispielanwendung werden D3-Dienstprogrammfunktionen verwendet, um das SVG-Liniendiagramm zu erstellen und der 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-Script ist jedoch in der <head>
der Seite enthalten, was das Parsen des restlichen Dokuments blockiert:
Mit zwei magischen Attributen kann der Parser entsperrt werden, wenn sie dem Script-Tag hinzugefügt werden:
async
sorgt dafür, dass Scripts im Hintergrund heruntergeladen und bei der ersten Gelegenheit nach dem Download ausgeführt werden.Mit
defer
werden Scripts im Hintergrund heruntergeladen und nach Abschluss des Parsings ausgeführt.
Da dieses Diagramm für die gesamte Seite nicht wirklich wichtig ist und sich höchstwahrscheinlich unterhalb des sichtbaren Bereichs befindet, prüfen Sie mit defer
, ob es nicht vom Parser blockiert wird.
Schritt 1: Script 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: Auf die richtige Reihenfolge der Vorgänge achten
Jetzt, da D3 ausgesetzt ist, wird script.js
ausgeführt, bevor D3 bereit ist, was zu einem Fehler führt.
Scripts mit dem defer
-Attribut werden in der Reihenfolge ausgeführt, in der sie angegeben wurden. Damit script.js
erst ausgeführt wird, wenn D3 fertig ist, fügen Sie defer
hinzu und verschieben Sie es in das <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>
Drittanbieterressourcen per Lazy Load laden
Alle Ressourcen, die „below the fold“ (mit Scrollen sichtbar) sind, eignen sich gut für Lazy Loading.
In der Beispiel-App ist ein YouTube-Video in einen iFrame eingebettet. So kannst du prüfen, wie viele Anfragen die Seite stellt und welche vom eingebetteten YouTube-Iframe stammen:
- Wenn Sie sich eine Vorschau der Website ansehen möchten, drücken Sie App ansehen und dann Vollbild .
- Drücken Sie „Strg + Umschalttaste + J“ (oder „Befehlstaste + Option + J“ auf einem Mac), um die Entwicklertools zu öffnen.
- Klicken Sie auf den Tab Netzwerk.
- Klicken Sie das Kästchen Cache deaktivieren an.
- Wählen Sie im Drop-down-Menü Drosselung die Option Schnelles 3G aus.
- Lade die Seite neu.
Im Bereich Netzwerk sehen Sie, dass für die Seite insgesamt 28 Anfragen gesendet und fast 1 MB komprimierte Ressourcen übertragen wurden.
Die von YouTube iframe
gesendeten Anfragen findest du in der Spalte Initiator anhand 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.
Wenn Sie die Anfragen nach Domain sortieren möchten, klicken Sie auf den Spaltentitel Domains.
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 es sei denn, die Nutzer scrollen tatsächlich nach unten, um das Video abzuspielen, sind all diese Assets nicht wirklich erforderlich.
Wenn Sie mit dem Lazy Loading für das Video warten, bis ein Nutzer nach unten zu diesem Bereich der Seite scrollt, verringern Sie die Anzahl der Anfragen, die von der Seite anfänglich gestellt werden. So werden die Daten der Nutzer gespeichert und das initiale Laden beschleunigt.
Eine Möglichkeit, Lazy Loading zu implementieren, ist die Verwendung des Intersection Observers, einer Browser-API, die benachrichtigt, wenn ein Element den Darstellungsbereich des Browsers betritt 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 in Standard-HTML-Elementen speichern können. Datenattribute können beliebig benannt werden, solange sie mit „data-“ beginnen.
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 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 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 Script-Tag in den Kopf des Dokuments 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);
Geben Sie observer
jetzt ein Zielelement an, das beobachtet werden soll (in diesem Fall der Video-Frame), 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 von IntersectionObserverEntry
-Objekten und das IntersectionObserver
-Objekt selbst. Jeder Eintrag enthält ein target
-Element und Eigenschaften, die unter anderem seine Abmessungen, seine Position und die Zeit beschreiben, zu der es in den Darstellungsbereich eingetreten ist. 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
ist gleich true
, wenn target
den Darstellungsbereich betritt. 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);
});
});
- Wenn Sie sich eine Vorschau der Website ansehen möchten, drücken Sie App ansehen und dann Vollbild .
- Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Optionstaste + J auf einem Mac), um die Entwicklertools zu öffnen.
- Klicken Sie auf den Tab Console.
Scrollen Sie nach oben und unten. Der Wert von isIntersecting
sollte sich ändern und das Zielelement sollte in der Console 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. Dieser Vorgang löst das Laden des Videos aus. Rufe dann nach dem Laden des Videos die Methode unobserve
auf dem observer
auf, um die Wiedergabe 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 noch einmal bewerten
Wenn Sie sehen möchten, wie sich die Größe und Anzahl der Ressourcen geändert hat, öffnen Sie den Bereich Netzwerk in den Entwicklertools und aktualisieren Sie die Seite noch einmal. Im Bereich Netzwerk sehen Sie, dass für die Seite 14 Anfragen und nur 260 KB gesendet wurden. Das ist eine deutliche Verbesserung.
Scrollen Sie jetzt auf der Seite nach unten und achten Sie auf den Bereich Netzwerk. Wenn Sie das Video aufrufen, sollten Sie sehen, dass die Seite zusätzliche Anfragen auslöst.
Vorabverbindung zu erforderlichen Ursprüngen herstellen
Sie haben nicht kritisches JavaScript verschoben und die YouTube-Anfragen mit Lazy Loading geladen. Jetzt 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 gesendet wird. Dieses Attribut eignet sich am besten für Ursprünge, die Ressourcen bereitstellen, die für die Seite erforderlich sind.
Die Lighthouse-Analyse, die Sie im ersten Schritt unter Vorabverbindung zu erforderlichen Ursprüngen herstellen ausgeführt haben, hat ergeben, dass Sie etwa 400 ms einsparen können, wenn Sie vorzeitige Verbindungen zu staticxx.facebook.com und youtube.com herstellen:
Da das YouTube-Video jetzt mit Lazy Loading geladen wird, bleibt nur noch staticxx.facebook.com, die Quelle des Widgets zum Teilen in sozialen Medien. Um eine frühzeitige Verbindung zu dieser Domain herzustellen, fügen Sie einfach ein <link>
-Tag zum <head>
des Dokuments hinzu:
<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 Codelab im Abschnitt Leistung messen aus, um eine weitere Lighthouse-Analyse auszuführen.