Open top menu

Wieso man Javascript nicht im Head lädt (und im Footer besser auch nicht)

Ich kann mich noch erinnern als Anfang der 90er Javascript noch ein außerirdisches Mysterium war, und zwei Zeilen Inline-Javascript das höchste der Gefühle. Erschwerend kam hinzu das ein gewisser Browser-Hersteller durchaus eigene Vorstellungen davon hatte, wie eine Skriptsprache was zu machen hat (ich erinnere nur an die verzweifelten Versuche VBScript zu etablieren). Heute tickt die Webwelt was anders: Es gibt nicht mehr eine CSS und eine JS-Datei. Wenn man sich den Quelltext einer WordPress- oder Drupal-Installation einmal anschaut, wird man förmlich erschlagen von vielen kleinen Dateien, die nachgeladen werden.

Was wiederum zur These führt, das Javascript im Head böse ist. Eine These, die übrigens von dem meisten Website-Optimierern vertreten wird. Warum ist das so? Der Browser geht (richtigerweise) davon aus, dass die Javascripte aufeinander aufbauen (als Beispiel: Bevor ich jQuery benutze, muss es ausgeliefert worden sein). Er lädt demnach also keineswegs die Javascript parallel vom Server, sondern fein eins nach dem anderen, damit es zu keinen Problemen kommt. Man sieht hier direkt, WO der Flaschenhals liegt: viele Javascript-Dateien, die alle hintereinander geladen werden, und somit die Auslieferung zum Client stark verlangsamen.

Was zur These führt, die Javascript im Footer zu laden. Lädt der Browser ein Skript, werden parallele Downloads generell geblockt – heißt: Es werden in der Zwischenzeit auch keine Bilder herunter geladen. Sind die Skripte im Footer, werden die JS zuletzt anstatt als Zweites (nach dem CSS) geladen, und der Benutzer sieht bereits den Content, bevor das Javascript in Aktion tritt.

Dies ist alles sehr nett, solange man es im CSS und bei der Erstellung der Webseite berücksichtigt hat. Geht man von vorneherein von diesem Prinzip aus, lässt sich eine Webseite mit Sicherheit geeignet programmieren, wendet man das Prinzip auf eine bereits bestehende (und alte) Seite an, kann man sein blaues Wunder erleben. Ein Flash of Unstyled Content ist dabei noch das kleinste Problem über, das man stolpern kann – vor allem, wenn die Seite meint, mit document.write Content erstellen zu müssen (Solls ja noch geben) kann das Ganze übel enden.

Prinzipiell ist die Idee also richtig, allerdings teilweise nicht anwendbar. Erschwerend kommt für eine mögliche Optimierung hinzu, dass der Browser wissen müsste, in welcher Reihenfolge die Skripte geladen werden müssen, falls diese aufeinander aufbauen. Dies ist aber nicht möglich. Als Beispiel könnte jQuery als Erstes, und 9 nicht artverwandte jQuery-Plugins durchaus parallel geladen werden.

Meistens kann auch das defer zum Einsatz gebracht werden. Als Erweiterung des <script>-Tags sagt es dem Browser, dass das zu ladende Javascript den Content nicht in dem Maße beeinflusst, das er das Rendern der Seite zum Laden des Skriptes unterbrechen müsste. Nutzt also schon mal ein wenig, aber die ultimative Lösung ist es auch noch nicht.

Viel interessanter ist da der Ansatz von head.js, das mit nur 2.5kb daher kommt, und das einzige direkte Javascript auf der gesamten Seite sein wird. Neben einigen anderen Schmankerln wie die Erweiterung von CSS (um zum Beispiel ein CSS passend zur Bildschirmauflösung anzubieten) kann man dem Skript seine eigenen Javascripte in einer geeigneten Reihenfolge übergeben. Head JS lädt diese dann parallel im Hintergrund und führt sie auch in einer geeigneten Reihenfolge hintereinander aus.

Wenn man also eine neue Seite aufbaut, kann man sich überlegen, ob man das JS evtl. in den Footer setzt. Wenn man dies von vorneherein berücksichtigt, sollte es zu keinen Problemen kommen – bei älteren Seiten macht eine Umstellung auf Head JS durchaus mehr Sinn. Am meisten Sinn macht es allerdings, auch bei neuen Seiten direkt auf Head JS zu setzen, um ein schnelles Rendern zu gewährleisten. Das hier bereits vorgestelle LABjs geht übrigens ähnlich vor, allerdings nicht so schön wie Head JS ;)

Guido
Geschrieben von Guido

Guido Mühlwitz ist Freiberufler mit Schwerpunkt HTML5, Zend Framework 2 / Node.js und individueller WordPress Plugin Entwicklung. Wenn er sich nicht gerade bei Twitter über PHP aufregt, bloggt er über aktuelle Themen aus dem Bereich der Anwendungsentwicklung.

6 Antworten auf Kommentar

  1. Avatar
    Februar 19, 2013

    „[…] Ich kann mich noch erinnern als Anfang der 90er Javascript noch ein außerirdisches Mysterium […]“ … Anfang der 90er?

    Javascript ist erst 1995 erschienen, und im Internet tatsächlich eingesetzt wurde Javascript ab Ende 1996… vielleicht mal die Gedächtnisdatenbank überprüfen? :)

    Antwort

  2. Avatar
    Januar 12, 2011

    @Jan

    Das kann aber auch nach hinten losgehen. Denn alles JavaScript, das hereinfliegt muss nicht nur geladen werden, sondern es wird, sobald es komplett ist, vom Browser sofort interpretiert und kompiliert. je größer der JS Code en bloq ist, desto länger blockiert der dann am Stück.

    Ein gutes Testobjekt dafür ist z.B. ein Custom-Build des Dojo Toolkit, in das Du mal alle Form-Widgets reinbackst. Das wird ziemlich groß und bringt für einen kurzen Moment selbst einen Core i7 zum stottern.

    Hast Du mehrere kleine Dateien, dann blockiert er entsprechend auch nur Häppchenweise, und dauert jeder dieser Happen weniger als 50ms, dann merkt der User erst gar nichts davon. Das Interface bleibt flüssig:

    http://vimeo.com/16241085

    Ebenfalls steigt der akkumulierte Gesamtdurchsatz, sobald Du mehrere Verbindungen parallel öffnen kannst, analog zu der Technik, die Download-Manager an den Tag legen um die Internetleitung auf Anschlag zu bekommen:

    http://calendar.perfplanet.com/2010/thoughts-on-performance/

    Am besten ist also eine Kombination: unabdingbares JavaScript auf eine Handvoll Dateien zusammengruppieren, und diese dann parallel laden lassen. Und alles was erst später notwendig ist auch erst bei onload hinterherladen, wenn die Leitung wieder frei ist, der User sich aber noch orientiert.

    Antwort

  3. Avatar
    Januar 12, 2011

    Ein wenig kann man dem Problem aber auch entgegenwirken, indem man das gesamte JavaScript zu einer Datei zusammenfassen lässt und dann auch noch mit GZIP behandelt.

    Da das ganze unter Drupal nicht ganz trivial ist, habe ich letztes Jahr einen Blogbeitrag zu dem Thema geschrieben.

    http://blog-das-oertchen.de/blog/2010/09/28/drupal-sinnvolle-optimierungen-teil-1

    Eventuell sollte ich meine Lösung aber trotzdem noch mit der head.js kombinieren, da derzeit eine große Datei im Head-Bereich geladen wird und ein Nachladen (zumindest bei meinen Projekten) wohl besser wäre.

    Antwort

  4. Avatar
    Januar 05, 2011

    Danke für den kleinen Finger. Die ganze Hand wäre nun ein entsprechendes WordPress-Plugin. ;)

    Antwort

  5. Avatar
    Januar 05, 2011

    Kleine Randnotiz: Aktuelle Browser, inklusive des IE8, sind im Unterschied zu früher mittlerweile in der Lage, mehrere, im Quelltext nachfolgende Scripte parallel zu einem aktuell in der Bearbeitung befindlichen Script vorzuladen, auch wenn der Rendervorgang nach wie vor an der aktuellen Stelle hängen bleibt. Das hat dann immerhin den Vorteil, dass in die nachfolgenden Blockiervorgänge (pro Script einer) nicht mehr die Ladezeit hineinfällt, sondern nur noch die reine Code-Aufbereitung und -Ausführungszeit.

    http://www.stevesouders.com/blog/2010/02/07/browser-script-loading-roundup/

    Zum Aufmöbeln alter und althergebracht aufgebauter Seiten verweise ich auf noch ein weiteres, brandneues Framework, das in der Lage ist, jene mit wenigen Handgriffen am Code (Änderungen an den src und type Attributen der Script-Tags) komplett zu „entblockieren“:

    ControlJS
    http://stevesouders.com/controljs/

    Antwort

Leave a comment