Sehr sehr schnelle Seiten - Website Performance Best Practice - Teil 2
Im heutigen zweiten Teil seines Überblicks über "Website Performance Best Practices" konzentriert sich Dirk Ginader auf die Optimierung von Javascript.
Im gestrigen ersten Teil haben wir uns mit der Optimierung von HTTP-Requests, HTML und CSS beschäftigt. Heute beschäftigen wir uns mit Javascript.
Optimierungen für Javascript
Javascript als letzes vor </body>
Eine noch relativ junge Erkenntnis ist, daß ein externes Javascript, bis es komplett geladen und vom Browser verarbeitet ist, den gesamten weiteren parallelen Lade- und Renderprozess des Browsers stoppt. Dies führt zu unnötigem Zeitverlust im Aufbau des Inhalts und des Designs. Um dies zu vermeiden, müssen alle externen Javascriptdateien als letztes Element vor dem abschließenden </body>-Tag eingebunden werden.
Minifizierung – was für CSS gut ist kann für Javascript nicht schlecht sein
Auch bei Javascript kann durch die Benutzung von Applikationen wie z.B. JSMin oder YUI Compressor sehr viel Dateigröße eingespart werden. Um dies ohne unerwünschte Fehlermeldungen zu überstehen sollte Javascript schon während der Entwicklung unbedingt ständig mit JSLint auf mögliche Probleme geprüft und somit auf eine bestmögliche Kompression vorbereitet werden.
Auch Javascript in Kombination schneller
Das Kombinieren aller externen Javascriptdateien reduziert die Anzahl der HTTP-Requests und sorgt damit für einen schnellen Download. Ed Eliot stellt ein komfortables PHP-Script zur Verfügung, das nicht nur das automatische Kombinieren von CSS- und Javascriptdateien ermöglicht, sondern auch noch gleichzeitig eine optionale JSMin-Optimierung anwenden kann.
Javascript mehrstufig zünden
Ebenso wichtig wie die effektiven Downloadzeiten ist die subjektiv wahrgenommene Geschwindigkeit, in der sich eine Webseite aufbaut. Insbesondere bei komplexeren Javascript-Applikationen kann es notwendig sein, dem Nutzer die notwendige Lade- und Initialisierungszeit subjektiv zu verkürzen. Dies kann durch einen mehrstufigen Aufbau erfolgen. Da das Javascript aus Performancegründen zuletzt geladen wird, ist es ein erster Schritt, diese Lücke mit einem positiven Feedback an den Nutzer zu schließen. Der folgende Javascript-Einzeiler eingebunden im <head> der Seite kann CSS frühzeitig über das Vorhandensein von Javascript informieren und somit das Aussehen der Webseite entsprechen anpassen, auch wenn die eigentliche Applikation noch läd:
- <script type="text/javascript">document.documentElement.className += ” js”;</script>
ermöglicht ein spezielles Javascript-Design im CSS durch Benutzung der .js Klasse
- #mein-javascript-modul{/* Design ohne Javascript hier */}
- .js #mein-javascript-modul{/* Design mit Javascript hier */}
Nicht auf window.onload
warten
Eine der wichtigsten Entwicklungen, um Javascript schneller Ausführen zu können, ist der onDomReady()
Event. Während der Klassiker window.onload
() wartet bis die gesamte Seite inklusive aller externen Dateien und Bildern geladen ist ermöglicht uns onDomReady()
Javascript gegen die Seite auszuführen sobald der DOM-Baum verfügbar ist und sorgt so für einen sehr großen Geschwindigkeitszugewinn.
Nach dem Laden ist vor dem Laden
Ist die erste Seite geladen, kann mit Javascript direkt weitergedacht werden. Wenn Elemente wie z.B. große Sprites auf den folgenden Seiten benötigt werden ist dies der Zeitpunkt, um diese bequem für den Nutzer vorzuladen, sodass die nächsten Seiten der Website eine zusätzliche Beschleunigung erfahren können.
Schnelleres Javascript durch Event Delegation
Je größer die Anzahl von Javascript-Events in einer Webseite, desto träger verhält sich diese bei der Benutzung. Ein sehr effektiver Weg, die Anzahl der Events gering zu halten, ohne Funktionalität einzubüßen ist Event Delegation. Hierbei wird davon profitiert, dass Javascript-Events sich automatisch im DOM nach oben bewegen (bubbling) und sich dadurch zwangsläufig an dem obersten gemeinsamen Knoten (z.B. <body>) treffen. Anstatt also wie gewohnt jedem Element dass z.B. auf einen Klick reagieren soll einen eigenen onclick()
-Handler zuzuweisen, macht man dies statt dessen nur einmal an dem obersten gemeinsamen Knoten und prüft dort, von welchem Kindknoten der Event ursprünglich ausgelöst wurde.
Generelle Optimierungen der externen Dateien
Komprimieren, wenn möglich
Eine kleine Einstellung in den Webserverkonfigurationen bringt einen grossen Vorteil: gzip. Einmal in z.B. Apache aktiviert, liefert der Server Dateien komprimiert und damit durchschnittlich über 70% kleiner an kompatible Browser aus. Ein unschätzbarer Vorteil, der häufig ungenutzt bleibt.
Browser Caches vollständig nutzen
Statische Dateien sollten so lange gecached werden wie möglich. Dies kann ebenfalls z.B. für Apache mit dem Header ExpiresDefault "access plus 10 years"
erreicht werden. Zu beachten ist hierbei aber, dass bei Aktualisierungen der gecachten Dateien eine Dateinamensänderung notwendig wird, um die neue Version sichtbar zu machen. So wird z.B. aus "logo.png" die Datei "logo1.png" wenn sie sich geändert hat oder aus "layout1.css" wird "layout2.css".
Nicht auf der gleichen Domain wie die Cookies ablegen
Der Browser schickt alle Cookies der aktuellen Domain bei jedem einzelnen Aufruf jeder Datei automatisch mit. Je nach Größe des Cookies ist dies ein signifikater Datentransfer, der z.B. bei einem Bild vollkommen unnötig ist. Um dies zu vermeiden macht es Sinn, alle statischen Dateien auf einer anderen Domain abzulegen, als die Inhaltsseiten. Nutzt man die "www"-Subdomain, reicht schon eine parallele Subdomain wie zum beispiel "statisch.meineseite.de". Nutzt man hingegen die top-level Domain "meineseite.de", werden automatisch alle Cookies auch an alle Subdomains geschickt. In diesem Fall sollte über die Verwendung einer zweiten Domain nachgedacht werden.
Mehrere Domains für statische Dateien
Ein weiterer Vorteil des Zugriffs auf die statischen Dateien über andere Domains ist eine alte Beschränkung von HTTP/1.1. Hier wurde definiert, dass Browser immer nur zwei Dateien parallel von einer Domain laden sollen. Zu Modemzeiten war dies auch sicherlich eine gute Idee. Heutzutage können wir diese Beschränkung einfach mit der Nutzung von mehreren Subdomains aushebeln. Nutzt man "statisch1.meineseite.de" und "statisch2.meineseite.de" abwechselnd als Pfad beispielsweise zu Bildern, kann der Browser schlagartig vier anstatt nur zwei Bilder gleichzeitig laden. Dies macht allerdings nur bis zu ca. vier parallelen Domains einen Vorteil aus, da jede Domain gleichzeitig auch einen zusätzlichen DNS-Lookup voraussetzt, der selbst wieder eine Verzögerung darstellt.
Danke
Das Exceptional Perfomance Team von Yahoo! hat den Artikel "Best Practices for Speeding Up Your Web Site" veröffentlicht und damit das Standardwerk für Frontend-Perfomance definiert. Ohne deren Vorarbeit wäre dieser Artikel nicht möglich gewesen.
Kommentare
Anonym
am 14.12.2008 - 10:31
Falsch, die wenn man example.com als Domain nutzt, werden die Cookies nicht an alles Subdomains geschickt, sondern nur, wenn man die Cookiedomain auf .example.com setzt.
Außerdem weiß ich nicht, warum es so einen großen unterschied machen sollte, wenn 100 Byte Cookies an der Server geschickt werden.
ChrisB
am 14.12.2008 - 18:21
@Anonym:
Cookies koennen auch mal groesser werden, als nur 100 Byte. Viele (fertige) Scripte setzen Dutzende von Cookies. (Klar, an der Stelle muesste man auch ansetzen, und schauen, was wirklich noetig, und was entbehrlich ist.)
Und das summiert sich eben, wenn der Cookie, der bspw. das Verhalten eines JavaScriptes steuern soll, auch beim Request fuer alle anderen Ressourcen wieder mitgeschickt wird (Bilder, ...), obwohl diese an ihm ueberhaupt nicht interessiert sind.
Elmar
am 15.12.2008 - 02:16
Auch wenn das dieser Artikel vielleicht implizit voraussetzt: Es wäre sinnvoll, JavaScript nur einzusetzen, wenn es einen echten Mehrwert für den Benutzer bedeutet, das heißt, nur auf wenigen bis keinen Seiten eines Sites.
Nur ein Beispiel: Ich besuchte Sites, deren Suche ohne Fehlermeldung keine Ergebnisse anzeigte, wenn JavaScript deaktiviert ist, während der Submit möglich ist.
Besser wäre, die Browser böten ein umfassendes Framework, sodass z.B. nicht jedesmal jQuery oder andere Frameworks geladen werden müssen.
Solange das nicht der Fall ist, wären Teilmengen aus Frameworks sinnvoll, die nur den Code für bestimmte Aufgaben enthalten, beispielsweise für Autocomplete oder Valididätsprüfung vor einem Submit.
Die Kommentare sind geschlossen.