Performance-Optimierung für Websites – Fortgeschrittene Tipps zur Optimierung der Lighthouse-Werte
An einem Punkt, wo wir neben einer besseren User Experience durch verkürzte Ladezeiten auch die Reduzierung von CO2-Emissionen im Blick haben, ist das Thema Performane-Optimierung nicht mehr wegzudenken. Wir zeigen euch, wie ihr die wichtigsten Punkte angeht.
Die Performance-Optimierung einer Website ist zum Standard geworden. Zu einem Zeitpunkt, an dem wir neben einer besseren User Experience durch verkürzte Ladezeiten auch die Reduzierung von CO2-Emissionen im Blick haben, ist das Thema nicht mehr wegzudenken. Wir zeigen euch, wie ihr die wichtigsten Punkte angeht, die direkt am Code der Website optimiert werden können.
Voraussetzungen
Ein guter Server, der die Website ausliefert, ist Voraussetzung, dass die aufgeführten Optimierungen auch ein spürbares Ergebnis liefern. Eine Website kann noch so gut optimiert sein, wenn der Server die Website zu langsam ausliefert, werden wir nie eine gute Performance erreichen.
Wir beziehen uns bei den aufgeführten Punkten vornehmlich auf die Informationen, die uns der Lighthouse-Performance-Test aus den Google Chrome DevTools liefert.
Neben der Erklärung, was die jeweilige Fehlermeldung bedeutet, zeigen wir in einem Code-Snippet das HTML-Markup zur Fehlerbehebung.
Standards, wie das Minifizieren, Komprimieren und Cachen von Dateien setzen wir voraus und gehen an dieser Stelle nicht weiter darauf ein.
Preload key requests
Via preload
kann dem Browser mitgeteilt werden, dass eine bestimmte Ressource früher abgerufen werden soll, als der Browser sie entdecken würde. Außerdem speichert der Browser vorgeladene Ressourcen im Cache, so dass sie bei Bedarf sofort verfügbar sind. Oft betrifft das die verwendeten Fonts:
<link rel="preload" href="...fonts/LatoRegular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
Ensure text remains visible during webfont load
Schriften sind oft große Dateien, die eine Weile zum Laden benötigen. Einige Browser verbergen Text, bis die Schrift geladen ist, was zum flash of invisible text (FOIT) führt.
Die einfachste Möglichkeit zu vermeiden, dass kein Text angezeigt wird, während benutzerdefinierte Schriften geladen werden, besteht darin, vorübergehend eine Systemschriftart anzuzeigen. Durch Hinzufügen der CSS-Eigenschaft font-display: swap;
innerhalb von @font-face
kann dies in den meisten modernen Browsern vermieden werden.
<style>
@font-face {
font-family: 'Lato';
src: url('.../fonts/LatoRegular.woff2') format('woff2');
font-style: normal;
font-weight: normal;
font-display: swap;
}
</style>
Eliminate render-blocking resources
Ziel ist es, Rendering-blockierende URLs zu reduzieren, indem kritische Ressourcen eingefügt, nicht-kritische Ressourcen zurückgestellt und unbenutzte Ressourcen entfernt werden.
Critical CSS
Ein Lösungsansatz ist, Critical CSS einzusetzen. Die Idee von Critical CSS ist, das Styling aller Elemente, die beim ersten Laden einer Unterseite im sichtbaren Bereich – »Above the Fold« – liegen, zu separieren und inline im HTML-<head>
zu laden.
Außerdem sollte die CSS-Datei nach Medien-Typ (Screen, Print, etc.) aufgeteilt werden, sodass ein nicht benötigter Medien-Typ vom Browser ignoriert und nicht geladen werden muss.
<!DOCTYPE html>
<html>
<head>
...
<style> /* critical */ </style>
</head>
<body>
<link rel="stylesheet" href="/assets/css/kb-style.css" media="screen" />
<link rel="stylesheet" href="/assets/css/kb-style-print.css" media="print" />
</body>
</html>
JavaScript zusammenfassen und reduzieren
Häufig wird auf Websites eine Vielzahl von JavaScripten für verschiedenste Funktionen geladen. Z. B. bringt so gut wie jedes WordPress-Plugin, das die Funktionalität via JavaScript erweitert, eine oder sogar mehrere JavaScript-Dateien mit. Diese erzeugen einzelne Requests. Durch Zusammenfassen der Scripte zu einer einzelnen Datei können diese vermieden, oder durch Priorisieren und dynamisches Nachladen verzögert werden.
Seit der Verfügbarkeit von HTTP/2, womit mehrere Requests parallel vom Server verarbeitet werden können, ist das Zusammenfassen aller Scripte zu einer einzelnen großen Datei nicht unbedingt der effizienteste Ansatz. Stattdessen kann es sinnvoller sein zu prüfen, welche Scripte auf der aktuellen Unterseite benötigt werden, und nur diese zu laden. Dadurch muss effektiv eine geringere Datenmenge geladen werden. An dieser Stelle nur der kurze Hinweis, dass dadurch unter Umständen das Thema Caching erschwert wird.
JavaScript asynchron oder verzögert laden
async
Ein weiterer Lösungsansatz besteht darin, möglichst kein JavaScript im Header zu laden, sondern asynchron im Footer.
Mit dem async
-Attribut im <script>
-Tag lädt der Browser das Script parallel zu anderen Ressourcen und beginnt parallel mit dem Aufbau der Seite. Sobald das Script geladen ist, entsteht eine Pause, weil der Browser das Script erst interpretieren muss.
Für Third Party-Scripte ist async ein Muss. Wenn der externe Server, von dem ein Script bereitgestellt wird, langsam ist, beeinflusst das Script die Performance der eigenen Seite sehr stark negativ.
Asynchrones Laden kann allerdings auch zu Schwierigkeiten führen, da es nicht vorhersehbar ist, wann das Script tatsächlich geladen und ausführbar ist. Einzelne Funktionen müssen gegebenenfalls umgeschrieben werden und mit entsprechenden Callbacks arbeiten.
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<script async src="/assets/js/kb_async-script.min.js"></script>
</body>
</html>
defer
Das defer
-Attribut im <script>
-Tag verspricht dem Browser, dass die Webseite nicht durch Anweisungen wie document.write
geändert wird. document.write
sollte sowieso vermieden werden! Der Browser verschiebt das Laden und Ausführen des Scripts, bis alle anderen Komponenten geladen und das DOM Processing abgeschlossen ist.
<!DOCTYPE html>
<html>
<head>
<script defer src="/assets/js/kb_defer-script.min.js"></script>
</head>
<body>
...
</body>
</html>
Defer offscreen images
Bilder, die nicht im Viewport – im sichtbaren Bereich der Website – liegen, müssen nicht geladen werden. Sowohl der Request als auch die Datenmenge kann initial eingespart werden. Erst, wenn sie durch Scrollen oder ein vergleichbares Event in den Viewport kommen, müssen sie nachgeladen werden. Das wird als »Lazy Loading« bezeichnet.
Moderne Browser unterstützen Lazy Loading nativ. Über die Ergänzung <loading="lazy">
im <img>
-Tag wird dem Browser mitgeteilt, dass er mit dem Laden des jeweiligen Bildes warten soll, bis es in den Viewport kommt – oder in die Nähe des Viewports, damit das Nachladen nicht sichtbar ist und es kein »Springen« im Layout gibt – auch als Layout Shift bezeichnet. Der Cumulative Layout Shift (CLS) wird ebenfalls im Lighthouse-Test und Performance mit geprüft.
<img
loading="lazy"
width="750"
height="750"
alt=""
src="/assets/img/img-750.webp"
>
Serve images in next-gen formats
Bilder sollten in einem web-optimierten Format, etwa WebP oder AVIF, ausgespielt werden. Diese neueren Formate bieten den Vorteil einer wesentlich stärkeren Komprimierung bei geringerem Qualitätsverlust. In WordPress kann dies relativ einfach und zuverlässig mit einem Plugin wie EWWW Image Optimizer automatisiert werden. Hier könnt ihr nachlesen, wie und in welchen Programmen WebP-Grafiken exportiert werden können.
Properly size images
Bilder sollten möglichst genau in der Größe ausgespielt werden, in der sie auch angezeigt werden. Bei einem Bildschirm mit einer Auflösung von 1920px mal 1080px und einem DPR-Wert von 1 (kein Retina, o. Ä.) brauchen Bilder, die in einer effektiven Größe von 320px mal 320px angezeigt werden, auch nur genau in dieser Größe geladen zu werden.
Um gleichzeitig Bilder für Geräte mit einem höheren DPR-Wert zur Verfügung zu stellen, kann das srcset
-Attribut in <img>
-Tags verwendet werden.
<img
loading="lazy"
width="750"
height="750"
alt=""
src="/assets/img/img-750.webp"
srcset="/assets/img/img-750.webp 750w,
/assets/img/img-325.webp 325w"
sizes="(max-width: 1023px) 100vw,
(min-width: 768px) 50vw,
(min-width: 1024px) 33vw"
>
Hier erfahrt ihr mehr über Responsive Images im Web.
Hallo Felix, wo wird der „Preload key requests“ denn eingefügt? Wäre sehr nett wenn du kurz erläuterst. Die Frage taucht immer wieder im Umfeld auf. Danke voraus!
Hallo Bimu, der Link-Tag muss im Head der Website eingefügt werden, also zwischen öffnendem und schließendem Head-Tag und vor dem Link zum CSS. In WordPress geht das z. B. in der functions.php mit der Action ‚wp_head‘. Siehe WordPress Code Reference. lg Felix
Hallo Jonas,
Danke für tollen Infos die du bereitstellst.
Hast du ein paar gute Ideen wie man Autoptimize optimal einsetzt?
Gruß Alex
Danke für die Tipps! Vor allem, so nachvollziehbar erklärt, hilft mir das echt weiter. Auf den allermeisten Seiten wird es so technisch erklärt, dass ich gar nicht mehr mitkomme.
Wie stehst du denn zu Optimierungsplugins wie W3 Total Cache?
Ich habe bisher damit gute Erfahrungen gemacht, habe aber den Eindruck, dass man da noch mehr rausholen kann.
Vielleicht schreibst du dazu mal einen Artikel?