Webdesign/Performance-Optimierung

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche
Schlanke Webseiten laden schnell!

Eine Webseite hat nicht nur möglichst gut auszusehen, sie sollte auch möglichst wenig übertragene Bytes haben. Dass die Bandbreiten für die Datenübertragung beim Durchschnittsanwender allmählich besser werden, bedeutet nicht, hier und jetzt zu klotzen, ohne Rücksicht auf den Netzverkehr (und damit auch die Latenz, die jeden einzelnen HTTP-Round-Trip verzögert) zu nehmen.

Dieses Tutorial zeigt, wie du Webseiten schlank und schnell gestaltet, indem du dich auf das Wesentliche konzentrierst und Unwesentliches weglässt.

Bandbreite und Latenz

Beide Begriffe charakterisieren die Möglichkeiten bzw. Begrenzungen der Netzwerk-Anbindung: Die Bandbreite gibt die maximale Datenmenge pro Zeiteinheit an, die übertragen werden kann. Während es früher mit einem Modem typischerweise 56 kBit/Sekunde waren, liegen heutige DSL- oder Glasfaseranschlüsse bei mehreren Hundert Megabit pro Sekunde, im LAN sind 100 MBit/s bis 1 GBit/s Standard.

Bandbreite Latenz.svg

Die Dauer der Signalübertragung zwischen Sender und Empfänger wird als Latenz bezeichnet und üblicherweise in Millisekunden angegeben. Die Latenz hängt von der Elektronik der Netzwerkkomponenten (Router, Switches), der Übertragungsart (Funk, Kabel oder Glasfaser) und der Leitungslänge ab. Allgemein ist die Latenz höher, je mehr Netzwerkkomponenten Pakete routen, zwischen verschiedenen Übertragungsarten wandeln müssen und je länger die Übertragungsstrecke ist. Datentransfer ist daher in einem lokalen Netzwerk stets "schneller" als interkontinental oder via Satellit.

Datenmengen

Scott Jehl legte in seinem Artikel „Planning for Performance“[1] das Augenmerk auf die sich immer weiter steigernde Datenmengen, die heutige Webseiten ausliefern. Während die durchschnittliche Webseite 1,7 MB groß ist, haben manche responsive Seiten wie disney.com, die für jeden Browser die passenden Frameworks, Grafiken und Skripte ausliefern, über 5 MB, teilweise sogar über 100 MB!

Gerade angesichts der Tatsache, dass Benutzer mobiler Geräte nicht nur über WLAN, sondern auch über 3G surfen, sollten Webseiten nicht nur responsiv, sondern auch schlank sein. Das Surfen im Mobilnetz bewirkt eine zeitliche Verzögerung von 2 Sekunden beim Seitenaufbau, da der Datenstrom vom Server zusätzlich noch den Funksender des Mobilfunknetzes passieren muss.

Auch wenn LTE und 4G diese Antwortzeiten verringert haben, ist mobiles Surfen an sich langsamer als Surfen mit WLAN oder in Kabelnetzen. Deshalb sollten Sie versuchen, die Anzahl der HTTP-Requests so gering wie möglich zu halten. Normalerweise blocken externe CSS-Dateien und JS-Skripte im Unterschied zu Grafiken das Rendering einer Seite. Durch das Nachladen von Stylesheets mit Hilfe von Skripten und nachträglichem Einfügen mittels document.write wird der schon gerenderte Seiteninhalt wieder verändert.

Empfehlung: Vermeide ein Laden der Seite, bevor die Stylesheets geladen sind. Dieses FOUC (Flash of unstyled Content) ist extrem ärgerlich und verzögert den Seitenaufbau.


Okay, so, without losing any media or functionality, without any noticeable reduction in quality and a significant *increase* in accessibility, I've got my client’s homepage from 5.2MB down to 130KB. Just webp conversion, stripping out the extraneous JavaScript and CSS and a simpler DOM. Lot of cowboys out there.
Large Heydon Collider
https://bildung.social/@heydon@front-end.social/112095132286608450

Einfluss pro HTTP-Round-Trip

Als HTTP-Round-Trip wird die gesamte HTTP-Anfrage (der Request) und -Antwort (der Response) bezeichnet.

HTTP-Round-Trip.svg

Jeder HTTP-Transfer besteht aus den HTTP-Headern und den Nutzdaten. Die HTTP-Header für Anfrage und Antwort betragen jeweils mehrere Hundert Byte, wie sich beispielsweise mit dem Netzwerk-Tab im Seiteninspektor nachvollziehen lässt[2]. Überschlagsmäßig lässt sich also mit 1 bis 2 Kilobyte allein an HTTP-Headern pro Round-Trip rechnen. Das wirkt sich insbesondere bei vielen kleinen Ressourcen (CSS, Icons, JavaScript-Snippets) aus. Zudem hat jeder einzelne Round-Trip eine vom Netzwerk bestimmte Latenz. Es ist daher sinnvoll die Anzahl (und Größe) an HTTP-Round-Trips zu reduzieren.

Multiplexing/Sprites

Bei der Verwendung vieler kleinen Ressourcen bietet es sich an diese nach Möglichkeit in einen Round-Trip zu kombinieren. CSS- und JavaScript-Snippets können in jeweils einer Bibliothek zusammengefasst werden. Bilder können als so genannte Sprites kombiniert werden, so dass an der entsprechenden Stelle im DOM nur der relevante Teil der Gesamtgrafik referenziert wird.

Datenkompression und -minimierung

Jedes zu übertragene Byte nutzt einen Teil der verfügbaren Bandbreite. Durch Kompression und Minimierung wird die zu übertragene Datenmenge reduziert und daher die Bandbreite besser ausgenutzt.

Minimierung

Bereits ohne Kompression lässt sich die Datenmenge durch Entfernen redundanter oder obsoleter Bytes reduzieren. Bei CSS- und JavaScript-Ressourcen ist dies als „Minifizierung“ bekannt:

  • Entfernen unnötiger Leerzeichen und Zeilenumbrüche. Im Idealfall können HTML-, SVG-, CSS- oder JavaScript-Ressourcen in nur einer einzigen Zeile übertragen werden. Das ist zwar nicht mehr benutzerfreundlich lesbar, aber dem jeweiligen Parser "egal".
  • Abkürzen von JavaScript-Variablen oder CSS-Identifiern, so dass deren Namen minimal kurz sind. (Diese Technik wird auch beim Verschleiern von Code verwendet und sollte am Besten mit separaten Tools erfolgen.)
  • Verzichten auf optionale HTML-Attribute, CSS-Regeln, ...
  • Zusammenfassen gleicher Inline-Styles in CSS-Regeln.
  • Ersetzen generischer HTML-div oder -span mit "semantischen" Klassen durch entsprechende HTML-Elemente, z.B. <section> statt <div class="section">.
  • Kondensation mehrfach verschachtelter div-Bäume in einen Container – und analog Kondensation von gruppierten Elementen in SVG.

Lazy Loading

Dies ist auch eine Form der Datenminimierung für den Zeitpunkt des Seitenaufrufs: Zu diesem Zeitpunkt (noch) nicht benötigte Inhalte werden erst einmal nicht geladen, sondern bei Bedarf wenn der entprechende Teil der Seite in den Viewport gelangt.

  • Für Bilder kann das loading="lazy"-Attribut angeben werden.
  • Andere (dynamische) Inhalte können erst bei Bedarf mit Fetch angefordert werden. Hier ist eine Fehlerbehandlung und Betrachtung der Barrierearmut notwendig, damit das Nachladen für alle zugänglich gestaltet ist und ein Fehlschlag nicht als Fehler beim Nutzer „aufschlägt“.

Anpassung an den Client

Bei Bildern ist es sinnvoll die für den jeweiligen Client (als Kombination aus Endgerät und Netzanbindung) optimalen Formate, Bildgrößen und Kompressionsraten zur Verfügung zu stellen. Das ist auf der Wiki-Seite Bilder im Internet/Formate und Größen näher beschrieben.

Transportkompression

HTTP überträgt Ressourcen per Default „so, wie sie sind“, d. h. unkomprimiert. Server können jedoch so konfiguriert werden, dass sie Daten komprimiert übertragen können; gängige Webserver in Produktivumgebungen (Apache, nginx) tun dies auch für bestimmte Inhalte automatisch (Default-Konfiguration) oder können entsprechend konfiguriert werden. Damit Inhalte komprimiert ausgeliefert werden, muss

  • ein Client im Accept-Encoding-Header mitteilen, dass und welche Kompressionsarten er „versteht“
  • der Server die Kompressionsmethode implementiert haben.

Ein Beispiel dafür ist in obiger Abbildung eines Round-Trips dargestellt:

  • Der Client spezifiziert Accept-Encoding: gzip, deflate, br, zstd.
  • Der Server unterstützt (mindestens) und verwendet gzip zur Kompression: Content-Encoding: gzip.

Statische Inhalte sollten wenn immer möglich komprimiert übertragen werden. (Server könnten hierfür intern einen eigenen Cache verwenden.) Bei dynamischen Inhalten (z. B. das Resultat eines PHP- oder CGI-Skripts) sollte man den CPU-Overhead der Kompression im Auge behalten. (Neuere Apache-Versionen scheinen auch dynamisch generierte Daten des Typs text/html mit gzip zu komprimieren.)

Die Effizienz der Kompression, also wie viel Netzwerk-Traffic gespart wird, ergibt sich aus der Content-Length und der tatsächlichen Dateigröße, wenn man den Inhalt der Ressource lokal unkomprimiert speichert. Der Content-Length-Header gibt nämlich die Anzahl der übertragenen Bytes der (ggf. komprimierten) Ressource an.

Caching

Unabhängig von den obigen Überlegungen sollte für jede statische Ressource Caching erlaubt werden und eine Information über die letzte Änderung oder ein Hashwert des Inhalts gesendet werden. Browser und Proxy-Server können so die Inhalte in ihrem Zwischenspeicher (Cache) vorhalten und müssen diese nicht bei jedem Aufruf erneut anfragen.

Testen

ToDo (weitere ToDos)

Zeigen, wie man eine Seite auf Page speed testet!

Matthias Scharwies (Diskussion) 07:06, 26. Apr. 2024 (CEST)


Siehe Auch

Weblinks

  1. alistapart.com: „Planning for Performance“ von Scott Jehl
  2. Mozilla Firefox Devtools: Network request details