« Zurück zum Magazine

Rasend schnelle Ladezeiten dank Prefetching, Preloading und Prerendering

Das Vorausladen von Inhalten war für Webentwickler lange Zeit eine nervenaufreibende Aufgabe. Viel Javascript-Trickserei war nötig, um einzelne Ressourcen wie Bilder vorausschauend im Cache des Nutzers abzulegen.

Dank neuer Techniken lässt sich das Prefetching, Preloading und Prerendering externer Ressourcen, aber auch kompletter HTML-Seiten, heute sehr einfach vom Browser erledigen.

Obwohl die Browser-Unterstützung noch recht unzureichend ist, macht der Einsatz von Preloading-Techniken bereits heute Sinn und ist vergleichsweise einfach zu implementieren. Nutzer, die über einen modernen Browser verfügen werden profitieren, die anderen haben keinerlei Nachteile. Ein schönes Beispiel für gelungenes Progressive-Enhancement.

Der folgende Artikel soll einen Überblick der möglichen Techniken bieten. Der grundsätzliche Aufbau ist dabei immer identisch und extrem simpel. Über das HTML <link>-Element wird im href-Attribut definiert, auf welche URL oder Ressource sich das Vorausladen beziehen soll. Im rel-Attribut wird schließlich angegeben, um welche Art des Preloadings es sich handelt.

Auf die Information, welcher Browser welches Feature unterstützt, wird in diesem Artikel ganz bewusst verzichtet. Zum einen ist eine Angabe meist nach wenigen Wochen bereits veraltet, zum anderen ist sie gemäß des Progressive-Enhancement-Ansatzes schlichtweg nicht notwendig.

DNS Prefetch

<link rel="dns-prefetch" href="//de.ryte.com">

Mittels dieser Zeile Code, die man im <head>-Element der Website platzieren sollte, gibt man dem Browser die Anweisung, lediglich die DNS-Auflösung durchzuführen. Das “Domain Name System” hat die Aufgabe, Domains mit ihren entsprechenden IP-Adressen zu verbinden.

Immer wenn man eine URL in die Adressleiste eines Browsers tippt, kann dieser mit der Domain beziehungsweise dem Host allein nichts anfangen. Stattdessen wird die IP-Adresse des Servers benötigt. Diese DNS-Auflösung benötigt Zeit; in der Regel zwischen 20 und 250 Millisekunden. Mit Hilfe des <link rel=”dns-prefetch”>-Elements kann man diesen Vorgang abkürzen, in dem die Umwandlung einer Domain oder URL bereits vor dem Klick oder der Weiterleitung erfolgt.

Preconnect

<link rel="preconnect" href="//de.ryte.com">

Die Preconnect- unterscheidet sich kaum von der DNS Prefetch - Eigenschaft. Einziger Unterschied ist, dass hier noch ein Schritt weiter gegangen und ein TCP- sowie TLS-Handshake durchgeführt wird. Neben dem Ermitteln der DNS-Informationen sind dies ebenfalls wichtige Vorgänge, die in der Regel einige Millisekunden benötigen.

Gerade wenn man Domains mit SSL-Zertifkat (z.B. https://de.ryte.com) prefetchen möchte, macht ein Einsatz des <link rel=”preconnect”>-Elements Sinn. Zudem lassen sich natürlich beide Elemente kombinieren:

<link rel="dns-prefetch" href="//de.ryte.com">
<link rel="preconnect" href="//de.ryte.com">

Prefetch

<link rel="prefetch" href="//de.ryte.com/image.jpg">

Der Wert “prefetch” klingt zwar fast identisch, sollte aber dennoch nicht mit dem oben beschriebenen “dns-prefetch” verwechselt werden. Diese Eigenschaft sollte vor allem verwendet werden, um statische Ressourcen wie Bilder, CSS- und Javascript-Dateien vorauszuladen. Dabei wird die komplette Datei heruntergeladen und im Browser-Cache abgelegt. Ein Prefetching von HTML-Dokumenten ist zwar auch möglich, jedoch folgen im weiteren Artikelverlauf noch effektivere Methoden.

Es ist zu beachten, dass man sich nicht darauf verlassen darf, dass eine Ressource heruntergeladen wird. Die Browser versuchen, ihre Kapazitäten geschickt einzusetzen. Der Firefox beispielsweise lädt eine per <link rel=”prefetch”>-Element definierte Datei nur herunter, sobald er sich im Leerlauf befindet und sonst keine Aufgaben mehr zu erfüllen hat. Zudem ignoriert er große Dateien vollständig, solange sich der Nutzer in einem langsamen Netzwerk befindet.

Nichtsdestotrotz eignet sich das Prefetching hervorragend, um beispielsweise Grafiken und Bilder vorauszuladen, die erst nach einer Javascript-Aktion oder einem CSS-Hover benötigt werden. In einem Online-Shop könnte man zudem die CSS-Datei für den Checkout-Bereich prefetchen, sobald der Besucher den ersten Artikel in den Warenkorb gelegt hat.

Subresource

<link rel="subresource" href="//de.ryte.com/image.jpg">

Die noch relativ junge Subresource-Eigenschaft ist vom Verhalten vergleichbar mit <link rel=”prefetch”>. Auch hier wird die angegebene Datei vom Server heruntergeladen und im Cache des Browsers abgelegt.

Der Unterschied liegt hier jedoch in der Prioritisierung. Bei Prefetch entscheidet wie erwähnt der Browser, ob und wann die Ressource benötigt wird. Subresource hingegen sagt aus, dass die Datei von enormer Wichtigkeit für die aktuelle Webseite ist und in Kürze benötigt wird. Dementsprechend weist der Browser dem Download eine weitaus höhere Priorität zu.

Wenn man sich nicht hundertprozentig sicher ist, dass eine Ressource in absehbarer Zeit benötigt wird, sollte man jedoch eher die Prefetch-Eigenschaft einsetzen. Bei der Anwendung von <link rel=”subresource”> läuft man ansonsten Gefahr, den Download anderer wichtiger Ressourcen zu blockieren.

Preload

<link rel="preload" href="//de.ryte.com/image.jpg" as="image">

Zum Zeitpunkt dieses Artikel liegt die Preload-Eigenschaft lediglich als erster W3C Working Draft vom Juli 2015 vor. Auch diese ist vergleichbar mit <link rel=”prefetch”>, genießt jedoch ebenfalls eine höhere Priorität. Zudem lässt sich via as-Attribut festlegen, in welchem Request-Context eine Ressource angefordert werden soll.

Da die Eigenschaft jedoch noch kein verabschiedeter Standard ist und von keinem Browser unterstützt wird, sollte man beim Produktiveinsatz Vorsicht walten lassen.

Prerender

<link rel="prerender" href="//de.ryte.com/blog/">

Die Prerender-Eigenschaft ist mit Abstand die mächtigste der vorgestellten Techniken; birgt jedoch auch die meisten Gefahren. Im Prinzip sorgt <link rel=”prerender”> dafür, dass eine URL samt sämtlicher benötigter statischer Ressourcen im Hintergrund bereits vollständig geladen und aufgebaut wird. Man könnte es sich so vorstellen, als öffnet man eine URL im Vorfeld in einem neuen Tab, der jedoch solange versteckt bleibt, bis der Besucher die Seite wirklich ansteuert. Die Ladezeit beim Wechsel auf eine vorgerenderte Webseite liegt in der Regel bei unter 50 Millisekunden; für das Auge also kaum wahrnehmbar.

Wie erwähnt gibt es beim Einsatz von Prerender einige Gefahrenquellen. Schließlich werden im Hintergrund sämtliche Aktivitäten ausgeführt, die auch bei einem realen Seitenaufruf stattfinden würden. Ist man beispielsweise in einem Online-Shop eingeloggt und lädt die Abmelden-Seite per Prerender, so ist man beim nächsten Seitenaufruf abgemeldet. Auch beim Einsatz eigener Tracking-Scripte (Google Analytics kann mit Prerender umgehen) ist Vorsicht geboten, da ebenfalls sämtliche Javascripte vollständig ausgeführt werden. Abhilfe schafft hier die Page Visibility API, die erkennen kann, ob eine Webseite gerade wirklich angezeigt wird.

Abbildung 1: Ob ein <link rel=”prerender”> funktioniert, lässt sich in den Chrome Entwicklerwerkzeugen im Network-Reiter überprüfen.

Vorgeladene Ressourcen lassen sich hier über den Filter “Other” bequem anzeigen. In dem Zusammenhang sollte man auch den Request-Header “Purpose” beachten, der vom Browser den Wert “prefetch” erhält.

Wann sollte ich welche Eigenschaft einsetzen?

Generell gibt es hier leider keine Musterlösung. Jede Methode hat ihre Vor- und Nachteile, die es im Kontext der Webseite oder des Projekts abzuwägen gilt. Sofern man über ausreichend Serverkapazitäten verfügt, macht ein Vorladen von Inhalten aber häufig Sinn. Gerade auf Webseiten, bei denen sich die folgende Interaktion des Besuchers voraussagen lässt, sollte man ein Prefetching oder Prerendering immer im Betracht ziehen.

Um einige Beispiele zu nennen:

  • Landingpages, bei denen ein Klick auf den Call-to-Action-Button zur nächsten Unterseite führt

  • Die URL der nächsten Seite, sofern ein Inhalt auf mehrere Unterseiten aufgeteilt wurde

  • Bild-Strecken, die aus mehreren einzelnen Unterseiten bestehen

  • Die nächste Seite eines Suchergebnis oder einer Artikel-Übersicht auf einem Blog

Königsdiziplin: Dynamisch auf Basis der Nutzeraktion vorladen

Ein gutes Preloading steht und fällt mit der Genauigkeit der vorausgesagten nächsten Aktion des Besuchers. Die oben genannten Beispiele zeigen, dass ein initial durchgeführtes Preloading oder -rendering in vielen Fällen Sinn machen kann. Noch präziser wird die Vorsage allerdings, wenn man sie auf Basis der realen Nutzerinteraktion trifft.

Um auch hier ein paar Beispiele zu nennen:

  • Sobald der Besucher auf einem Image-Slider mit der Maus über die Navigationspfeile fährt, wird das nächste Bild vorgeladen.

  • Eine Unterseite kann vorgeladen werden, wenn man erkennt, dass sich der Mauszeiger in Richtung des entsprechenden Links bewegt.

  • Bei Seiten die Lazy Loading unterstützen, könnte man <link rel=”prefetch”> nutzen, um nachzuadene Bilder während des Scrollens bereits vorzuladen, ohne andere Browser-Aufgaben zu gefährden.

Abschließend ein simpler Javascript- beziehungsweise jQuery-Codeschnipsel, mit dem sämtliche Links auf einer Seite bei einem Mouseover deren jeweilige URLs via <link rel=”prerender”> vorladen. In dieser Form ist der Code jedoch ausdrücklich nicht für den Produktiveinsatz geeignet.

Zusammenfassung

PrefetchingTabelle-03

Sicher, dass Deine Website schnell genug ist?

Veröffentlicht am Oct 20, 2015 von Torben Leuschner