Bekämpfe den Vorablade-Scanner des Browsers nicht

Finden Sie heraus, was der Vorablade-Scanner im Browser ist, wie er die Leistung verbessert und wie Sie ihn vermeiden können.

Ein Aspekt der Optimierung der Seitengeschwindigkeit, der bisher übersehen wurde, besteht darin, sich mit den internen Strukturen des Browsers vertraut zu machen. Browser nehmen bestimmte Optimierungen vor, um die Leistung auf eine Weise zu verbessern, die wir als Entwickler nicht können – aber nur, solange diese Optimierungen nicht unbeabsichtigt verhindert werden.

Eine interne Browseroptimierung, die Sie verstehen sollten, ist der Browser Preload Scanner. In diesem Beitrag erfahren Sie, wie der Vorablade-Scanner funktioniert und, was noch wichtiger ist, wie Sie vermeiden können, ihn zu stören.

Was ist ein Vorabladescanner?

Jeder Browser verfügt über einen primären HTML-Parser, der Roh-Markup tokenisiert und in ein Objektmodell verarbeitet. Das Ganze wird so lange fortgesetzt, bis der Parser eine Pause macht, wenn er eine blockierende Ressource findet, z. B. ein Stylesheet mit einem <link>-Element oder ein Script, das mit einem <script>-Element ohne async- oder defer-Attribut geladen wurde.

HTML-Parser-Diagramm.
Abb. 1:Ein Diagramm, das zeigt, wie der primäre HTML-Parser des Browsers blockiert werden kann. In diesem Fall wird der Parser auf ein <link>-Element für eine externe CSS-Datei ausgeführt, das den Browser daran hindert, den Rest des Dokuments zu parsen oder überhaupt zu rendern, bis der CSS-Code heruntergeladen und geparst wurde.

Bei CSS-Dateien wird sowohl das Parsen als auch das Rendering blockiert, um ein Flash of Unstyled Content (FOUC) zu verhindern. Das ist der Fall, wenn kurz eine Version einer Seite ohne Stil zu sehen ist, bevor Stile darauf angewendet werden.

Die web.dev-Startseite ohne Stil (links) und im Zustand mit benutzerdefinierten Stilen (rechts)
Abb. 2:Ein simuliertes Beispiel für FOUC. Links ist die Startseite von web.dev ohne Stile zu sehen. Rechts sehen Sie dieselbe Seite mit angewendeten Stilen. Der Status ohne Stil kann in Flash auftreten, wenn der Browser das Rendering nicht blockiert, während ein Stylesheet heruntergeladen und verarbeitet wird.

Der Browser blockiert außerdem das Parsen und Rendern der Seite, wenn <script>-Elemente ohne defer- oder async-Attribut erkannt werden.

Dies liegt daran, dass der Browser nicht sicher wissen kann, ob ein bestimmtes Skript das DOM ändert, während der primäre HTML-Parser noch seine Aufgabe ausführt. Aus diesem Grund ist es üblich, JavaScript am Ende des Dokuments zu laden, sodass die Auswirkungen des blockierten Parsings und des Renderings marginal sind.

Dies sind gute Gründe dafür, warum der Browser sowohl das Parsing als auch das Rendering blockieren sollte. Allerdings ist es nicht wünschenswert, diese wichtigen Schritte zu blockieren, da sie die Sendung anhalten können, da sie das Erkennen anderer wichtiger Ressourcen verzögern. Glücklicherweise tun Browser ihr Möglichstes, um diese Probleme mit einem sekundären HTML-Parser, dem sogenannten Preload Scanner, zu entschärfen.

Ein Diagramm des primären HTML-Parsers (links) und des Vorladescanners (rechts), bei dem es sich um den sekundären HTML-Parser handelt.
Abb. 3:Ein Diagramm, das zeigt, wie der Vorabladescanner parallel zum primären HTML-Parser funktioniert, um Assets spekulativ zu laden. Hier wird der primäre HTML-Parser blockiert, da er CSS lädt und verarbeitet, bevor er mit der Verarbeitung des Bild-Markups im <body>-Element beginnen kann. Der Vorabladescanner kann jedoch im Roh-Markup nach dieser Bildressource suchen und mit dem Laden beginnen, bevor die Blockierung des primären HTML-Parsers aufgehoben wird.

Die Rolle eines Vorladescanners ist spekulativ. Das bedeutet, dass er unbearbeitetes Markup untersucht, um Ressourcen zu finden, die opportunistisch abgerufen werden können, bevor der primäre HTML-Parser sie ansonsten entdecken würde.

So erkennen Sie, ob der Vorabladescanner funktioniert

Der Vorabladescanner ist vorhanden, weil Rendering und Parsen blockiert sind. Wenn es diese beiden Leistungsprobleme nie gäbe, wäre der Vorabladescanner nicht sehr nützlich. Der Schlüssel, um herauszufinden, ob eine Webseite vom Preload-Scanner profitiert, hängt von diesen Blockierphänomenen ab. Dazu können Sie eine künstliche Verzögerung für Anfragen einführen, um herauszufinden, wo der Vorabladescanner funktioniert.

Nehmen Sie diese Seite mit einfachem Text und Bildern mit einem Stylesheet als Beispiel. Da CSS-Dateien sowohl das Rendering als auch das Parsen blockieren, wird durch einen Proxy-Dienst eine künstliche Verzögerung von zwei Sekunden für das Stylesheet eingeführt. Durch diese Verzögerung lässt sich in der Netzwerkabfolge leichter erkennen, wo der Vorladescanner arbeitet.

Das Netzwerk-Wasserfalldiagramm des WebPageTest-Netzwerks zeigt eine künstliche Verzögerung von zwei Sekunden, die auf das Stylesheet angewendet wird.
Abb. 4:WebPageTest Wasserfalldiagramm für eine Webseite, das auf einem Mobilgerät über eine simulierte 3G-Verbindung in Chrome ausgeführt wird. Obwohl das Stylesheet durch einen Proxy künstlich um zwei Sekunden verzögert wird, bevor der Ladevorgang beginnt, wird das Bild, das sich später in der Markup-Nutzlast befindet, vom Preload-Scanner erkannt.

Wie Sie an dem Wasserfall sehen können, erkennt der Vorabladescanner das <img>-Element, auch wenn das Rendern und das Parsen von Dokumenten blockiert sind. Ohne diese Optimierung kann der Browser während des Sperrzeitraums keine opportunistischen Daten abrufen und mehr Ressourcenanfragen würden aufeinanderfolgende und nicht gleichzeitig ausgeführt.

Nachdem das Spielzeugbeispiel aus dem Weg gerissen ist, schauen wir uns einige reale Muster an, bei denen der Vorladescanner abgewehrt werden kann und wie wir diese beheben können.

async Scripts eingefügt

Angenommen, Ihre Datei <head> enthält HTML-Code, der Inline-JavaScript enthält, z. B.:

<script>
  const scriptEl = document.createElement('script');
  scriptEl.src = '/yall.min.js';

  document.head.appendChild(scriptEl);
</script>

Injizierte Scripts haben standardmäßig den Wert async. Wenn dieses Script eingeschleust wird, verhält es sich also so, als wäre das Attribut async darauf angewendet. Das bedeutet, dass sie so schnell wie möglich ausgeführt wird und das Rendering nicht blockiert. Klingt optimal, oder? Wenn Sie jedoch davon ausgehen, dass dieses Inline-<script> auf ein <link>-Element folgt, das eine externe CSS-Datei lädt, erhalten Sie ein suboptimales Ergebnis:

Dieses WebPageTest-Diagramm zeigt den Preload-Scan, der beim Injizieren eines Skripts verhindert wird.
Abb. 5:Ein WebPageTest-Netzwerkwasserfalldiagramm einer Webseite, das in Chrome auf einem Mobilgerät über eine simulierte 3G-Verbindung ausgeführt wird. Die Seite enthält ein einzelnes Stylesheet und ein eingefügtes async-Skript. Der Preload-Scanner kann das Skript während der Blockierungsphase nicht erkennen, da es in den Client eingeschleust wurde.

Schauen wir uns an, was passiert ist:

  1. Bei 0 Sekunden wird das Hauptdokument angefordert.
  2. Bei 1, 4 Sekunden kommt das erste Byte der Navigationsanfrage an.
  3. Nach 2, 0 Sekunden werden das CSS und das Bild angefordert.
  4. Da der Parser das Laden des Stylesheets blockiert und das Inline-JavaScript, das das async-Skript einschleust, nach diesem Stylesheet nach 2,6 Sekunden erscheint, ist die von diesem Skript bereitgestellte Funktion nicht so schnell verfügbar, wie es möglich wäre.

Dies ist nicht optimal, da die Anforderung für das Skript erst erfolgt, nachdem das Stylesheet heruntergeladen wurde. Dadurch wird die Ausführung des Skripts verzögert. Da das <img>-Element hingegen im vom Server bereitgestellten Markup sichtbar ist, wird es vom Vorabladescanner erkannt.

Was passiert also, wenn Sie ein reguläres <script>-Tag mit dem async-Attribut verwenden, anstatt das Skript in das DOM zu injizieren?

<script src="/yall.min.js" async></script>

Das ist das Ergebnis:

Eine Netzwerkabfolge im WebPageTest-Netzwerk, die zeigt, wie ein asynchrones Skript, das mithilfe des HTML-Skriptelements geladen wird, weiterhin vom Scanner zum Vorabladen gefunden werden kann, obwohl der primäre HTML-Parser des Browsers beim Herunterladen und Verarbeiten eines Stylesheets blockiert ist.
Abb. 6:Ein WebPageTest-Netzwerkwasserfalldiagramm für eine Webseite, das in Chrome auf einem Mobilgerät über eine simulierte 3G-Verbindung ausgeführt wird. Die Seite enthält ein einzelnes Stylesheet und ein einzelnes async-<script>-Element. Der Preload-Scanner erkennt das Skript während der Blockierungsphase des Renderings und lädt es gleichzeitig mit dem CSS-Code.

Es besteht die Versuchung, diese Probleme mit rel=preload zu beheben. Das würde zwar funktionieren, aber es kann einige Nebenwirkungen haben. Warum sollten Sie rel=preload verwenden, um ein Problem zu beheben, das sich vermeiden lässt, wenn Sie ein <script>-Element nicht in das DOM einschleusen?

Ein WebPageTest-Wasserfall, der zeigt, wie der Ressourcenhinweis &quot;rel=preload&quot; verwendet wird, um die Erkennung eines asynchron eingeschleusten Skripts zu fördern, allerdings auf eine Weise, die unbeabsichtigte Nebeneffekte haben kann.
Abb. 7:Ein WebPageTest-Netzwerkwasserfalldiagramm für eine Webseite, das auf einem Mobilgerät über eine simulierte 3G-Verbindung in Chrome ausgeführt wird. Die Seite enthält ein einzelnes Stylesheet und ein eingefügtes async-Skript. Das async-Skript wird jedoch vorab geladen, damit es schneller gefunden werden kann.

Das Vorabladen "behebt" das Problem hier, bringt jedoch ein neues Problem mit sich: Das Skript async in den ersten beiden Demos wird – obwohl es in <head> geladen wurde – mit der Priorität "Niedrig" geladen, während das Stylesheet mit der Priorität "Höchste" geladen wird. In der letzten Demo, bei der das async-Skript vorab geladen wurde, wird das Stylesheet weiterhin mit der höchsten Priorität geladen, die Priorität des Skripts wurde jedoch auf "Hoch" hochgestuft.

Wenn die Priorität einer Ressource erhöht wird, weist der Browser ihr mehr Bandbreite zu. Das bedeutet, dass die erhöhte Priorität des Skripts zu Bandbreitenkonflikten führen kann, obwohl das Stylesheet die höchste Priorität hat. Das kann ein Faktor bei langsamen Verbindungen oder bei sehr großen Ressourcen sein.

Die Antwort ist ganz einfach: Wenn beim Start ein Skript benötigt wird, muss der Vorladescanner nicht durch eine Injektion in das DOM deaktiviert werden. Experimentieren Sie bei Bedarf mit der Platzierung des <script>-Elements sowie mit Attributen wie defer und async.

Lazy Loading mit JavaScript

Lazy Loading ist eine sehr gute Methode zur Schonung von Daten, die häufig auf Bilder angewendet wird. Manchmal wird Lazy Loading jedoch auf Bilder angewendet, die sozusagen „above the fold“ (ohne Scrollen sichtbar) sind.

Dies führt im Zusammenhang mit dem Vorabladescanner zu Problemen mit der Auffindbarkeit von Ressourcen und kann unnötig lange dauern, bis eine Referenz zu einem Bild erkannt, heruntergeladen, decodiert und präsentiert wird. Nehmen wir als Beispiel dieses Bild-Markup:

<img data-src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

Die Verwendung des Präfixes data- ist ein gängiges Muster in Lazy Loading mit JavaScript. Wenn das Bild in den Darstellungsbereich gescrollt wird, entfernt der Lazy Loader das Präfix data-. Im vorherigen Beispiel wird data-src also zu src. Bei dieser Aktualisierung wird der Browser aufgefordert, die Ressource abzurufen.

Dieses Muster ist erst problematisch, wenn es auf Bilder angewendet wird, die sich beim Start im Darstellungsbereich befinden. Da der Scanner zum Vorabladen das Attribut data-src nicht auf dieselbe Weise liest wie ein Attribut src (oder srcset), wurde die Bildreferenz nicht früher gefunden. Schlimmer noch, das Laden des Bildes wird erst nach dem Herunterladen, Kompilieren und Ausführen von JavaScript durch Lazy Loader verzögert.

Ein WebPageTest-Netzwerk-Wasserfalldiagramm, das zeigt, wie ein Lazi-Loading-Bild, das sich beim Start im Darstellungsbereich befindet, zwangsläufig verzögert wird, da der Scanner für das Vorabladen die Bildressource nicht finden kann und nur geladen wird, wenn das für Lazy Loading für die Arbeit erforderliche JavaScript geladen wird. Das Bild wird viel später entdeckt, als es sein sollte.
Abb. 8:Ein WebPageTest-Netzwerkwasserfalldiagramm einer Webseite, das in Chrome auf einem Mobilgerät über eine simulierte 3G-Verbindung ausgeführt wird. Die Bildressource wird unnötigerweise Lazy Loading, obwohl sie beim Start im Darstellungsbereich sichtbar ist. Dadurch wird der Preload-Scanner übergangen und eine unnötige Verzögerung verursacht.

Je nach Größe des Bildes – sie kann auch von der Größe des Darstellungsbereichs abhängen – kann es ein mögliches Element für Largest Contentful Paint (LCP) sein. Wenn der Scanner zum Vorabladen die Bildressource nicht im Voraus spekulativ abrufen kann – möglicherweise während des Zeitraums, an dem das Rendering des Stylesheets der Seite blockiert wird –, leidet der LCP.

Die Lösung besteht darin, das Bild-Markup zu ändern:

<img src="/sand-wasp.jpg" alt="Sand Wasp" width="384" height="255">

Dies ist das optimale Muster für Bilder, die sich beim Start im Darstellungsbereich befinden, da der Vorabladescanner die Bildressource erkennt und schneller abrufen kann.

Netzwerk-Wasserfalldiagramm von WebPageTest, das ein Ladeszenario für ein Bild im Darstellungsbereich beim Start darstellt Das Bild wird nicht langsam geladen, d. h., es ist nicht vom Script abhängig, das geladen werden soll. Das bedeutet, dass der Vorablade-Scanner es früher erkennen kann.
Abb. 9:Ein WebPageTest-Netzwerkwasserfalldiagramm für eine Webseite, das in Chrome auf einem Mobilgerät über eine simulierte 3G-Verbindung ausgeführt wird. Der Preload-Scanner erkennt die Bildressource, bevor CSS und JavaScript geladen werden, sodass der Browser beim Laden einen Vorsprung hat.

Das Ergebnis in diesem vereinfachten Beispiel ist eine Verbesserung des LCP bei langsamen Verbindungen um 100 Millisekunden. Dies mag nicht nach einer großen Verbesserung erscheinen, aber wenn man bedenkt, dass die Lösung eine schnelle Markup-Korrektur ist und dass die meisten Webseiten komplexer sind als diese Beispiele. Das bedeutet, dass LCP-Kandidaten unter Umständen mit vielen anderen Ressourcen um Bandbreite kämpfen müssen, sodass Optimierungen wie diese immer wichtiger werden.

CSS-Hintergrundbilder

Denken Sie daran, dass der Scanner für das Vorabladen des Browsers das Markup scannt. Andere Ressourcentypen wie CSS werden nicht gescannt. Für Bilder, auf die durch die background-image-Property verwiesen wird, werden möglicherweise Bilder abgerufen.

Wie HTML verarbeiten Browser CSS in einem eigenen Objektmodell, das als CSSOM bezeichnet wird. Wenn beim Erstellen des CSSOMs externe Ressourcen erkannt werden, werden diese Ressourcen zum Zeitpunkt der Erkennung angefordert und nicht vom Vorabladescanner.

Angenommen, der LCP-Kandidaten Ihrer Seite ist ein Element mit der CSS-Eigenschaft background-image. Beim Laden der Ressourcen geschieht Folgendes:

Ein WebPageTest-Netzwerk-Wasserfalldiagramm zeigt eine Seite mit einem LCP-Kandidaten, der über die Eigenschaft „Hintergrundbild“ aus CSS geladen wurde. Da sich das LCP-Kandidatenbild einem Ressourcentyp befindet, den der Scanner zum Vorabladen nicht prüfen kann, wird das Laden der Ressource verzögert, bis das CSS heruntergeladen und verarbeitet wurde. Dadurch wird die Paint-Zeit des LCP-Kandidaten verzögert.
Abb. 10:Ein WebPageTest-Netzwerkwasserfalldiagramm für eine Webseite, das in Chrome auf einem Mobilgerät über eine simulierte 3G-Verbindung ausgeführt wird. Der LCP-Kandidaten der Seite ist ein Element mit der CSS-Eigenschaft background-image (Zeile 3). Das angeforderte Bild wird erst abgerufen, wenn es vom CSS-Parser gefunden wurde.

In diesem Fall ist der Vorladescanner nicht so stark besiegt, wie er unbeteiligt ist. Wenn ein LCP-Kandidaten auf der Seite jedoch aus einer background-image-CSS-Eigenschaft stammt, sollte das Bild vorab geladen werden:

<!-- Make sure this is in the <head> below any
     stylesheets, so as not to block them from loading -->
<link rel="preload" as="image" href="lcp-image.jpg">

Dieser rel=preload-Hinweis ist zwar klein, hilft dem Browser jedoch, das Bild schneller zu finden, als er es sonst tun würde:

Ein WebPageTest-Netzwerk-Wasserfalldiagramm mit einem CSS-Hintergrundbild (dem LCP-Kandidaten), das aufgrund des Hinweises rel=preload viel schneller geladen wird Die LCP-Zeit verbessert sich um etwa 250 Millisekunden.
Abb. 11:Netzwerkabfolgediagramm einer Webseite von WebPageTest auf einem Mobilgerät über eine simulierte 3G-Verbindung. Der LCP-Kandidaten der Seite ist ein Element mit der CSS-Eigenschaft background-image (Zeile 3). Der rel=preload-Hinweis hilft dem Browser, das Bild etwa 250 Millisekunden früher als ohne den Hinweis zu erkennen.

Mit dem Hinweis rel=preload wird der LCP-Kandidaten früher erkannt, wodurch die LCP-Zeit verringert wird. Mit diesem Hinweis lässt sich das Problem zwar beheben. Besser ist es aber vielleicht herauszufinden, ob der LCP-Kandidaten für das Bild über CSS geladen werden muss. Mit einem <img>-Tag haben Sie mehr Kontrolle darüber, wie ein Bild geladen wird, das für den Darstellungsbereich geeignet ist, und gleichzeitig zulassen, dass der Vorabladescanner es erkennt.

Zu viele Ressourcen inline einbinden

Inline ist eine Praxis, bei der eine Ressource innerhalb des HTML-Codes platziert wird. Mit der Base64-Codierung können Sie Stylesheets in <style>-Elementen, Skripts in <script>-Elementen und praktisch jeder anderen Ressource einfügen.

Das Inline-Inline-raten von Ressourcen kann schneller sein als das Herunterladen, da keine separate Anfrage für die Ressource ausgegeben wird. Sie befindet sich direkt im Dokument und wird sofort geladen. Es gibt jedoch erhebliche Nachteile:

  • Wenn Sie Ihren HTML-Code nicht im Cache speichern – und dies bei einer dynamischen HTML-Antwort nicht möglich ist –, werden die Inline-Ressourcen nie im Cache gespeichert. Dies wirkt sich auf die Leistung aus, da die Inline-Ressourcen nicht wiederverwendbar sind.
  • Selbst wenn Sie HTML im Cache speichern können, werden Inline-Ressourcen nicht zwischen den Dokumenten geteilt. Dies reduziert die Caching-Effizienz im Vergleich zu externen Dateien, die im Cache gespeichert und für den gesamten Ursprung wiederverwendet werden können.
  • Wenn Sie zu viele Inline-Inhalte inline einfügen, verzögert der Vorablade-Scanner später im Dokument Ressourcen, da der Download dieser zusätzlichen Inline-Inhalte länger dauert.

Sehen wir uns diese Seite als Beispiel an. Unter bestimmten Bedingungen ist der LCP-Kandidat das Bild oben auf der Seite und der CSS-Code befindet sich in einer separaten Datei, die von einem <link>-Element geladen wird. Die Seite verwendet außerdem vier Web-Schriftarten, die als separate Dateien von der CSS-Ressource angefordert werden.

Ein WebPageTest-Netzwerk-Wasserfalldiagramm einer Seite mit einer externen CSS-Datei, in der vier Schriftarten referenziert werden. Das LCP-Kandidatenbild wird zu gegebener Zeit vom Vorabladescanner erkannt.
Abb. 12:Ein WebPageTest-Netzwerkwasserfalldiagramm für eine Webseite, das in Chrome auf einem Mobilgerät über eine simulierte 3G-Verbindung ausgeführt wird. Der LCP-Kandidaten der Seite ist ein Bild, das aus einem <img>-Element geladen wurde, aber vom Vorlade-Scanner erkannt wird, weil sich der CSS-Code und die für den Seitenaufbau erforderlichen Schriftarten in separaten Ressourcen befinden. Dadurch wird die Ausführung des Vorablade-Scanners nicht verzögert.

Was passiert, wenn der CSS-Code und alle Schriftarten als base64-Ressourcen angegeben sind?

Ein WebPageTest-Netzwerk-Wasserfalldiagramm einer Seite mit einer externen CSS-Datei, in der vier Schriftarten referenziert werden. Der Vorabladescanner erkennt das LCP-Bild erheblich verzögert .
Abb. 13:Ein WebPageTest-Netzwerkwasserfalldiagramm für eine Webseite, das in Chrome auf einem Mobilgerät über eine simulierte 3G-Verbindung ausgeführt wird. Der LCP-Kandidaten der Seite ist ein Bild, das von einem <img>-Element geladen wird. Das Inline-Inline-Element des CSS-Codes und seiner vier Schriftressourcen in „`“ verzögert jedoch das Erkennen des Bildes durch den Vorablade-Scanner, bis diese Ressourcen vollständig heruntergeladen sind.

Die Auswirkungen des Inline-Objekts haben in diesem Beispiel negative Auswirkungen auf den LCP – und auf die Leistung im Allgemeinen. Die Version der Seite, die keine Inline-Elemente enthält, malt das LCP-Bild in etwa 3,5 Sekunden. Auf der Seite, auf der alles inline platziert wird, erscheint das LCP-Bild erst nach etwas mehr als sieben Sekunden.

Hier kann mehr als nur der Vorlade-Scanner gespielt werden. Die Inline-Schriftarten ist keine gute Strategie, da base64 ein ineffizientes Format für Binärressourcen ist. Ein weiterer Faktor, der eine Rolle spielt, ist, dass externe Schriftartenressourcen nur heruntergeladen werden, wenn dies durch CSSOM als erforderlich erachtet wird. Wenn diese Schriftarten als Base64-konform angegeben sind, werden sie heruntergeladen, unabhängig davon, ob sie für die aktuelle Seite benötigt werden oder nicht.

Könnte ein Vorabladen die Dinge hier verbessern? Sehr gern. Sie könnten das LCP-Bild vorab laden und die LCP-Zeit reduzieren. Wenn Sie jedoch potenziell nicht im Cache speicherbaren HTML-Code mit Inline-Ressourcen aufblähen, hat dies andere negative Auswirkungen auf die Leistung. Auch First Contentful Paint (FCP) ist von diesem Muster betroffen. In der Version der Seite, die keine Inline enthält, beträgt FCP etwa 2,7 Sekunden. In der Version, in der alles enthalten ist, dauert FCP etwa 5,8 Sekunden.

Seien Sie sehr vorsichtig, wenn Sie Elemente in HTML einfügen, insbesondere base64-codierte Ressourcen. Im Allgemeinen wird es nicht empfohlen, mit Ausnahme von sehr kleinen Ressourcen. So wenig wie möglich inline, denn zu viel wird mit dem Feuer gespielt.

Markup mit clientseitigem JavaScript rendern

Es gibt keinen Zweifel: JavaScript wirkt sich definitiv auf die Seitengeschwindigkeit aus. Entwickler verlassen sich nicht nur darauf, wenn sie für Interaktivität sorgen, sondern sie nutzen sie auch für die Bereitstellung von Inhalten selbst. Dies führt in vielerlei Hinsicht zu einer besseren Erfahrung für Entwickler, die jedoch nicht immer auch für die Nutzer gleich ist.

Ein Muster, das den Preload-Scanner umgehen kann, ist das Rendern von Markup mit clientseitigem JavaScript:

Netzwerk-Wasserfall von WebPageTest, der eine einfache Seite mit Bildern und Text zeigt, die vollständig im Client in JavaScript gerendert werden. Da das Markup in JavaScript enthalten ist, kann der Vorablade-Scanner keine der Ressourcen erkennen. Alle Ressourcen werden aufgrund der zusätzlichen Netzwerk- und Verarbeitungszeit, die JavaScript-Frameworks benötigen, zusätzlich verzögert.
Abb. 14:Ein WebPageTest-Netzwerkwasserfalldiagramm einer clientseitig gerenderten Webseite, die auf einem Mobilgerät über eine simulierte 3G-Verbindung in Chrome ausgeführt wird. Da der Inhalt in JavaScript enthalten ist und zum Rendern ein Framework benötigt, wird die Bildressource im vom Client gerenderten Markup im Preload-Scanner verborgen. Das entsprechende vom Server gerenderte Ergebnis ist in Abb. 9 zu sehen.

Wenn Markup-Nutzlasten vollständig in JavaScript im Browser enthalten sind und von diesem gerendert werden, sind alle Ressourcen in diesem Markup für den Vorabladescanner praktisch unsichtbar. Dadurch wird das Erkennen wichtiger Ressourcen verzögert, was sich sicherlich auf den LCP auswirkt. In diesen Beispielen ist die Anfrage für das LCP-Bild im Vergleich zur entsprechenden vom Server gerenderten Version, für die kein JavaScript erforderlich ist, deutlich verzögert.

Dies weicht etwas vom Schwerpunkt dieses Artikels ab, aber die Auswirkungen des Renderings von Markups auf den Client gehen weit über das Verhindern des Vorabladescanners hinaus. Zum einen führt die Einführung von JavaScript zu einer unnötigen Verarbeitungszeit, die sich auf Interaction to Next Paint (INP) auswirken kann.

Außerdem führt das Rendern extrem großer Markup-Mengen auf dem Client mit höherer Wahrscheinlichkeit zu langen Aufgaben als die gleiche Menge an Markup, die vom Server gesendet wird. Abgesehen von der zusätzlichen Verarbeitung durch JavaScript ist der Grund dafür, dass Browser die Markups vom Server streamen und das Rendering so aufteilen, dass lange Aufgaben vermieden werden. Vom Client gerenderte Markups hingegen werden als einzelne, monolithische Aufgabe verarbeitet, die neben INP auch die Messwerte für die Reaktionszeit von Seiten wie Total Blocking Time (TBT) oder First Input Delay (FID) beeinflussen kann.

Die Abhilfe für dieses Szenario hängt von der Antwort auf diese Frage ab: Gibt es einen Grund, warum das Markup Ihrer Seite nicht vom Server bereitgestellt und auf dem Client gerendert werden kann? Wenn die Antwort „Nein“ lautet, sollten Sie nach Möglichkeit serverseitiges Rendering (SSR) oder statisch generiertes Markup in Betracht ziehen, da der Vorladescanner so wichtige Ressourcen im Voraus erkennen und opportunistisch abrufen kann.

Wenn Ihre Seite JavaScript benötigt, um Funktionen an einige Teile des Markups Ihrer Seite anzufügen, können Sie dies mit SSR entweder mit einfachem JavaScript oder mit der Hydration tun, um das Beste aus beiden Welten herauszuholen.

Helfen Sie dem Vorablade-Scanner dabei,

Der Preload-Scanner ist eine äußerst effektive Browser-Optimierung, mit der die Seiten während des Startvorgangs schneller geladen werden. Indem Sie Muster vermeiden, die es daran hindern, wichtige Ressourcen im Voraus zu finden, erleichtern Sie sich nicht nur die Entwicklung für sich selbst. Sie schaffen auch bessere Nutzererfahrungen, die zu besseren Ergebnissen bei vielen Messwerten führen, einschließlich einiger Web Vitals.

Hier noch einmal die folgenden Punkte, die Sie aus diesem Post mitnehmen sollten:

  • Der Browser Preload Scanner ist ein sekundärer HTML-Parser, der vor dem primären Parser sucht, wenn dieser blockiert ist, um Ressourcen zu finden, die er früher abrufen kann.
  • Ressourcen, die nicht in dem vom Server bei der ersten Navigationsanfrage bereitgestellten Markup vorhanden sind, können vom Vorladescanner nicht erkannt werden. So kann der Vorabladescanner unter anderem blockiert werden:
    • Einfügen von Ressourcen in das DOM mit JavaScript, z. B. Skripte, Bilder, Stylesheets oder etwas anderes, das in der anfänglichen Markup-Nutzlast vom Server besser geeignet wäre.
    • Lazy Loading von Bildern oder iFrames, die ohne Scrollen sichtbar sind, mithilfe einer JavaScript-Lösung
    • Rendering von Markup auf dem Client, das Verweise auf Dokument-Unterressourcen mit JavaScript enthalten kann
  • Der Vorabladescanner scannt nur HTML. Es prüft nicht die Inhalte anderer Ressourcen, insbesondere von CSS, die möglicherweise Verweise auf wichtige Assets wie LCP-Kandidaten enthalten.

Wenn Sie aus irgendeinem Grund ein Muster nicht vermeiden können, das sich negativ auf die Fähigkeit des Vorladescanners zur Beschleunigung der Ladeleistung auswirkt, beachten Sie den Ressourcenhinweis rel=preload. Wenn Sie rel=preload doch verwenden, testen Sie in Lab-Tools, ob Sie damit den gewünschten Effekt erzielen. Zu guter Letzt sollten Sie nicht zu viele Ressourcen vorab laden, denn wenn Sie alles priorisieren, passiert nichts.

Ressourcen

Hero-Image aus Unsplash von Mohammad Rahmani .