Website Performance ist ein sehr weitläufiges Thema und erstreckt sich über nahezu alle Aspekte der Webentwicklung. So ist es auf der Serverseite möglich, mit cleverem Caching von dynamisch generiertem Markup, dem Optimieren und Reduzieren von Datenbankabfragen und dem Setzen der wichtigen Expires und Cache-Control Header sehr schnell möglich, einen hohen Grad an Performance zu erreichen. Auf der Clientseite hingegen finden sehr häufig die meisten Geschwindigkeitsverluste statt.
Die folgende Liste erhebt keinen Anspruch auf Vollständigkeit, sondern stellt vielmehr eine Auswahl von clientseitigen Optimierungsmöglichkeiten dar, die grundsätzlich jeder Webseite gut tun und einfach zu implementieren sind:
Dies ist die allgemeinste Regel dieser Liste und gleichzeitig auch die Wichtigste. Im gesamten Ablauf des Ladens einer Webseite sind die HTTP-Abfragen die grössten Bremsen, die dankbarer Weise aber auch am Einfachsten zu beheben sind. Viele der folgenden Regeln beziehen sich hierauf. Bei einer HTTP-Abfrage geht viel Zeit verloren, weil beispielsweise die Headerinformationen bei der Anforderung jeder einzelnen Datei vom Client an den Server geschickt werden und auch wieder zurückgeliefert werden. Dies sind teure Bytes, die hier von meist redundanten Datenpaketen verschwendet werden. Eine noch viel deutlichere Verzögerung sind die Latenzzeiten der Webserver, die – bevor sie die Anfrage verarbeiten können – erst einmal reagieren müssen. Je nach Belastung des Servers und der Entfernung zum Client kann sich dies bis zu mehreren wertvollen Sekunden hinziehen.
CSS oder Javascript haben inline in der HTML Seite nichts verloren. In der Regel sind diese in externen Dateien viel besser aufgehoben, da sie sie dort vom Browser gecached werden und somit ohne Performanceverlust von der gesamten Website genutzt werden können ohne immer wieder neu geladen werden zu müssen.
Die Reihenfolge der Elemente im Markup bestimmt Ihre Wichtigkeit und den Zeitpunkt wann sie vom Nutzer wahrgenommen werden können. Banner oder externe Widgets werden naturgemäß langsamer geladen als der Inhalt der Seite, der sie einbindet. Daher sollten sie idealerweise auch erst nach dem Inhalt im Markup referenziert werden. Es fühlt sich für den Nutzer subjektiv schneller an, den Inhalt der Seite zu sehen und auf die Banner oder Widgets zu warten als umgekehrt.
Für Photografien und Grafiken mit sehr großem Farbumfang wie z.B. ein Verlauf ist JPEG die erste Wahl. Für Grafiken mit einer geringeren Anzahl von Farben empfiehlt es sich, dem 8 bit PNG dem Vorzug vor dem Klassiker GIF zu geben, da das PNG effektiver komprimiert und dadurch fast immer in der kleineren Datei resultiert.
Nahezu jedes Grafikprogramm schreibt Informationen über sich selbst und das Bild in die Datei. Während diese Informationen bei der Bearbeitung durchaus sinnvoll sein können, stellen Sie bei der Darstellung im Internet meist nur unnötigen Ballast dar. Hilfsprogramme wie pngcrush oder der Webservice smush.it entfernen diese ungenutzten Bits und reduzieren so effektiv Downloadzeit.
Im Gegensatz zum Rendern herkömmlicher opaker Grafiken muss der Browser Grafiken mit Alphatransparenzen sehr häufig neu berechnen, um die entstehenden Mischungen korrekt wiedergeben zu können. Dies strapaziert den Browser und damit das Betriebssystem mit erhöhter Prozessorlast und grösserem Arbeitsspeicherverbrauch, was wiederum in hässlichem Ruckeln bei Animationen oder beim Scrollen resultieren kann.
Eine sehr effektive Technik um HTTP-Requests zu reduzieren, ist aus vielen kleinen Bildern ein Großes zu machen. Dies ist ausschließlich bei CSS-Hintergrundbildern sinnvoll, da nur diese über das "background-position"-Attribut das Anzeigen eines Bildausschnittes ermöglichen. Es empfiehlt sich, Bilder zu Sprites zu kombinieren, die inhaltlich und farblich zueinander passen, um ein intelligentes Caching zu ermöglichen und die Farbpaletten klein zu halten. Der CSS Sprite Generator z.B. kann dies bequem automatisieren und auch noch direkt das notwendige CSS generieren.
Man sollte nicht glauben, daß ich dies hier erwähnen muss, aber zu große Bilder, die im HTML kleiner skaliert werden, sind mit die beliebtesten Performance-Bremsen überhaupt. Leider sind dem Entwickler hier häufig die Hände gebunden da diese Sünde meist von unwissenden Content Management System Nutzern begangen wird. Hier hilft nur Nachsitzen und lernen.
Neben dem Inhalt ist das Grunddesign eines der wichtigsten Seitenbestandteile, die dem Nutzer fehlen, wenn sie nicht sofort sichtbar sind. Um dies zu erreichen, muss das CSS im <head> mit dem <link> Element eingebunden sein. Wird das CSS nicht im <head> sondern im <body> verlinkt oder es wird nicht das <link> Element sondern @import zur Einbindung genutzt, kann dies zum unschönen "Flash of unstyled Content (FOUC)", einem Aufblitzen des unformatierten Inhalts, führen.
Viele CSS-Eigenschaften können auf verschiedene Arten geschrieben werden. Auch wenn es übersichtlicher ist z.B. die verschiedenen Hintergrundeigenschaften einzeln Zeile für Zeile zu definieren, so ist es mit Blick auf die Dateigrößesinnvoller, die Eigenschaften in Ihrer Kurzform zusammenzufassen.
So wird z.B. aus:
body{
background-color:#000000;
background-attachment:fixed;
background-image:url(pic.png);
background-position:left;
background-repeat:no-repeat;
}
folgende Kurzform:
body{background:#000 fixed url(pic.png) left no-repeat}
Deutlich verkleinert werden können CSS-Dateien durch das Anwenden spezieller CSS-Kompressor-Applikationen wie z.B. CSS Tidy oder YUI Compressor. Diese können den CSS-Code auf verschiedene Arten optimieren. Die einfachste Methode ist das Entfernen von unnötigen Leerzeichen und Zeilenumbrüchen. Zusätzlich können aber auch noch fortgeschrittene Techniken wie z.B. das automatische Zusammenfassen von redundanten Eigenschaften und das Kombinieren von Anweisungen in deren Kurzform angewandt werden.
Das Aufteilen der Styles in mehrere logisch getrennte und strukturierte CSS-Dateien ist während des Entwicklungsprozess unerlässlich. Sobald die Seite live ist, sind die resultierenden zusätzlichen HTTP-Requests jedoch in der Regel ein Performanceproblem. Ein einfaches Kombinieren der einzelnen Dateien in der richtigen Reihenfolge behebt diesen Makel sehr einfach. In Ausnahmefällen von mehreren sehr großen Stylesheets kann das parallele Laden einzelner Dateien den Performanceverlust der vermehrten HTTP-Requests wieder ausgleichen und zu einem schnelleren Endergebnis führen. Hier gilt es (wie immer) durch Testen zum bestmöglichen Ergebnis zu kommen.
Nicht während des Ladens sondern während der Benutzung einer Webseite stellen sich CSS-Expressions als Geschwindigkeitssünder heraus. Der Internet Explorer führt diese in CSS eingebetteten Javascriptanweisungen nämlich nicht nur dann aus, wenn es sinnvoll wäre, sondern bei absolut jeder Gelegenheit. Dies wirkt sich insbesondere dann negativ aus, wenn man die CPU für andere rechenintensive Operationen gut brauchen könnte wie z.B. für Animationen.
In den brachialen Anfangszeiten des World Wide Webs machte Dirk Ginader sein Hobby zum Beruf und gründete die Unit Interactive einer großen Werbeagentur in Mainz.
Nach fast 9 Jahren folgte der Webstandards und Accessibility Enthusiast dem Ruf von Yahoo! nach London, um dort dem Web-Development-Team und der Accessibility-Task-Force beizutreten.
In seiner Freizeit entwickelt er, spricht und bloggt über Web Development im Allgemeinen und barrierefreies Javascript im Besonderen.
Bitte die Hausregeln beachten. Alle Kommentare werden auf werbliche Links/Nicknames geprüft und gegebenenfalls gelöscht.
Kommentar-Feed für diesen Beitrag
Die Kommentarfunktion ist zur Zeit leider deaktiviert.
Wder
linknochstylesind innerhalb vonbodyerlaubt, wie soll ich da ein externes Stylesheet einbinden?Kommentar von Jeriko - 13. Dezember 2008 um 10:42
@Jeriko
Externe Stylesheets müssen im
<head>verlinkt werden. Siehe Absatz: "CSS wird im <head> verlinkt"Kommentar von Dirk Ginader - 13. Dezember 2008 um 10:56
Jeriko meinte, dass der Tipp, CSS im Header einzubinden reichlich überflüssig ist, weil <link> und <style> sowieso nur dort erlaubt sind. Also sind wir uns ja alle einig.
Bleibt der gute Tipp, @import bleiben zu lassen.
Kommentar von Nathanael - 13. Dezember 2008 um 12:40
Guter Hinweis.
Leider ist die Tatsache, daß Styles ausserhalb des <head> invalide sind, für sehr viele kein Grund das nicht zu tun…
Kommentar von Dirk Ginader - 13. Dezember 2008 um 13:28
Wunderbares Roundup, Dirk. Danke dafür.
Kommentar von j4k3 - 13. Dezember 2008 um 14:20
Ganz herzlichen Dank fuer einen ausfuerlichen und interessanten Aufsatz! Optimiere gerade eine Webseite eines Klients. Ihre Tips haben mir die Arbeit wesentlich erleichtert!
Kommentar von Andrey Esaulov - 14. Dezember 2008 um 17:33
Es ist nicht eher so, dass ein mit @import eingebundenes Stylesheet die White Page Zeit erhöht (ähnlich einer im head refernzierten JS-Datei), aber eben keinen FOUC erzeugt?
Kommentar von alexander farkas - 14. Dezember 2008 um 23:32
Skalieren von Bildern durch width und height im img-tag: Ich könnte mir einen Grund vorstellen, Bilder auf 50% zu skalieren (doppelt so lang und hoch speichern): Wird beim Firefox 3 oder – soweit ich weiß – im IE die Seite vergrößert, werden die Bilder mit vergrößert, außer es ist anders eingestellt, was aber in den wenigsten Fällen vorausgesetzt werden kann.
Insbesondere Fotos sehen dann () und unscharf aus, wenn die Quelle vergrößert werden muss.
Kommentar von Elmar - 15. Dezember 2008 um 01:51
Interessant! Vor allem das mit der "Kombination reduziert HTTP-Requests" war mir neu. Gibt es irgendwelche speziellen Tipps für Wordpress Seiten?
Kommentar von Manuel - 16. Dezember 2008 um 04:23
@Manuel
Die gibt es tatsächlich!
Mein hochgeschätzter Kollege Marco hat das Wordpress Plugin WP-CSS-Streamliner entwickelt welches automatisch alle CSS Dateien eines Wordpress Blogs kombiniert, optimiert und gzip komprimiert.
Kommentar von Dirk Ginader - 16. Dezember 2008 um 08:59
Hallo,
Noch ein Tip für Script Datein.
Wenn die nicht in bestimmten rein folge oder Dokumentinhalt generieren (zum Beispiel kein document.write in JS bentuzen) kann man dem Script-Tag das Attribut defer="false" setzen dann werden die Scripte gleichzeitig geladen anstatt nacheinander.
defer
Kommentar von Nico - 16. Dezember 2008 um 14:25
Vielen Dank auch von mir! Die hinweise waren auch für mich sehr nützlich!
Kommentar von Thomas - 17. Dezember 2008 um 15:18
Es gibt auch den HTTP-Header Link. Wenn man darüber das Stylesheet redundant auch angibt, muß der Browser nicht auf die Ergebnisse des HTML-Parsers warten, um die Adresse des Stylesheets herauszufinden.
Das ist besonders interessant für Handhelds, Mobiltelefone etc.
Zur Menge der HTTP-Requests: Gerade bei Seiten, die per Script generiert werden, vergessen die Autoren oft Content-Length. Das ist aber wichtig, um dem UA Pipelining zu ermöglichen, also die Bündelung mehrerer Requests.
Und wenn man Gzip benutzt, sind Basteleien an den Leerstellen in CSS und JS Zeitverschwendung. Sie ändern nahezu nichts an der übertragenen Dateigröße.
Kommentar von Thomas Scholz - 17. Dezember 2008 um 16:01