Sonntag, 3. März 2013

DOM Load mit sinnvoller Ladereihenfolge von JS und CSS beschleunigen

Für den Einsatz von Javascript-Widgets wie Slideshows, Lighboxes, und vielleicht noch den einen oder anderen Ajax-Request muss man beachten, dass man die Libraries und CSS-Files dazu in korrekter Reihenfolge lädt. Durch geschickte Deklarationsreihenfolge der Libraries lässt sich die Zeit verringern, bis die Website angezeigt wird.

Tipp: Deklarationsreihenfolge von CSS und JS beachten

Immer erst die CSS-, und erst danach die JS-Deklarationen - sofern dies die Applikationslogik zulässt. Wieso? Der Grund liegt in der Art der Parallelisierung der Downloads dieser Ressourcen.

Die meisten Browser blockieren den Download von im Dokument angegebenen Ressourcen nach einem Script-Tag, bis der Inhalt des Script-Tags gedownloadet, geparst und fertig ausgeführt ist. Dies ist soweit logisch, denn die Javascripts müssen sequentiell abgearbeitet werden, da sie unter Umständen das DOM verändern und von Aktionen vorangehender Scripts abhängig sein könnten. Anders sieht das bei CSS aus: Dies sind lediglich Styling-Informationen, und können allesamt parallel heruntergeladen werden (d.h. in der Regel 6 Files pro Domain aufs Mal, je nach Browser). Natürlich kann es sein, dass eine CSS-Rule eine andere wieder überschreibt, aber das führt nicht zu Inkonsistenzen im DOM.

Würde man nun also 2 externe Javascript-Dateien referenzieren, und danach 2 CSS-Dateien, so würden die CSS-Dateien erst heruntergeladen, nachdem die 2 Javascripts sequentiell durchgelaufen sind. Vorher blockiert der Browser jeden weiteren Ressourcen-Download. Dies sieht etwa so aus:


<script ... />
<script ... />
<link rel="stylesheet" ... />
<link rel="stylesheet" ... />

   50ms | 100ms | 150ms | 200ms |
--> JS1 --> JS2  
               --> CSS1
               --> CSS2


Die beiden JS werden geladen, und dann folgt der Rest parallel. Wie würde es aber aussehen, wenn wir zuerst die CSS, und dann die JS laden würden?


<link rel="stylesheet" ... />
<link rel="stylesheet" ... />
<script ... />
<script ... />  

   50ms | 100ms | 150ms | 200ms |
--> CSS1
--> CSS2
--> JS1 --> JS2

Angenommen, alle Files haben 50ms zum Laden, so hatten wir zuerst 150ms Ladezeit, nun sind es noch 100ms. Damit haben wir 30% Performance raus geholt.

Fazit

Weit hergeholt? Nein. Dieses Beispiel illustriert lediglich 2 Javascripts und 2 CSS-Dateien, alle von gleicher Grösse. In der realen Welt sieht es ganz anders aus. Fremdlibraries werden wie wild referenziert und  oft auch verkettet geladen, und eben in einer für den Browser ungünstigen Reihenfolge. Mit einer sinnvollen Parallelisierung holt man selbst bei guten Roundtrips schnell mal 50-100ms raus.

Natürlich könnte man nun sagen, man habe meinen Artikel über die Optimierung mittels Cache-Control-Header gelesen, und die JS-Dateien würden ja nur einmal heruntergeladen, und dann aus dem Browser-Cache bedient werden. Dies mag für subsequente Page-Aufrufe stimmen. Aber: Die JS-Dateien müssen dennoch jedes Mal geparst und ausgeführt werden, und das kostet Zeit. Auf einem Core-i7 mit Google Chrome sind dies bei der weit verbreiteten jQuery Library etwa 20ms, mit dem IE7 sind es immerhin ca. 100ms. Und dies bei jedem Seitenaufruf...

Fussnote

Natürlich gibt es diverse Ausnahmen, welche ich in diesem Artikel nicht erwähnt habe. Zum Beispiel lässt sich dem <script> Tag das "async" Attribut anhängen, womit die Scripts nicht aufeinander warten müssen. Des weiteren kennen moderne Browser intelligente Prediction-Modelle, über welche sie vorzubestimmen in der Lage sind, ob weitere Ressourcen schon mal gedownloadet, aber noch nicht ausgeführt werden sollen. Darauf bin ich natürlich nicht eingegangen, auch wenn moderne Browser diese Modelle in gewissen Situationen durchaus umsetzen. Hält man sich aber an obige Regel (Css-vor-Javascript), muss man sich darüber ja gar nicht erst den Kopf zerbrechen und ist immer auf der sicheren Seite.

Keine Kommentare:

Kommentar veröffentlichen