Javascript optimal in HTML einbinden

Um die Ladezeiten einer HTML Seite und damit deren Ranking bei Google zu optimieren, werden im Hinblick auf Javascript zwei Maßnahmen empfohlen:

  1. Eine Einbindung der externen Javascript Ressourcen möglichst weit unten in einer HTML Seite (unmittelbar vor dem </body> Tag).
  2. Asynchrones Laden der Skripte mittels dem Attribut async.

In der Praxis ist dies insbesondere für sehr große Webprojekte relevant, die schon aufgrund des Traffics auf mehreren Servern verteilt arbeiten. Für den überwiegenden Teil der „Ein-Server Projekte“, ist eine schnelle Internet-Anbindung sowie ein leistungsfähiger Webserver kombiniert mit ein paar Tricks meist vollkommen ausreichend.

Da die Javascript Ressourcen hinter dem Inhalt der Webseite eingebunden werden, können deren Funktionen bei den vorher im HTML Teil integrierten Scripts nicht unmittelbar genutzt werden. Zusätzlich bringt die Nutzung der Attribute „async“ und „defer“ bei der Einbindung auch die Reihenfolge der Ressourcen durcheinander. Das führt für den Hobby-Programmierer zu dem Problem, dass er sich nicht auf die Verfügbarkeit seiner notwendigen Bibliotheken und Funktionen zu bestimmten Zeitpunkten verlassen kann. Er verzichtet also auf diese durchaus sinnvollen Zeit-Optimierungen, oder verwendet „Krücken“ um dem Problem aus dem Weg zu gehen.

Auch ich hatte das Problem, dass ich gerne in Inline Scripts für Formulare schon jquery verwenden, dieses aber erst am Ende der Seite laden wollte. Und an „async“ konnte ich gar nicht denken …

jquery.js erst am Ende einer Seite einbinden – aber schon vorher nutzen

Eine Einbindung aller nachzuladenden Javascripts am Ende einer HTML Seite, also vor dem schließenden </body>, und nicht im <head> ist sehr sinnvoll. Dies führt jedoch dazu, dass jquery scripte innerhalb der HTML Seite vor Einbindung der jquery Bibliothek nicht ausgeführt werden können, da jquery ja noch nicht zur Verfügung steht.

Nun könnte man über ein kleines klassisches Javascript per SetTimeout() immer wieder prüfen bis jquery zur Verfügung steht und erst dann den gewünschten Code ausführen. In Einzelfällen könnte dies auch sinnvoll sein, doch spätestens wenn mehrere jquery Scriptteile im HTML Code benötigt werden, wird es irgendwann äußerst umständlich.

Auf der Suche nach einer Lösung, stieß ich im Web an mehreren Stellen auf eine interessante und flexible Umsetzung, die es sogar erlaubt jquery.js asynchron zu laden.

Das besondere an dieser Lösung ist die Tatsache, dass ich die übliche jquery Kurz-Notation schon vor dem Laden des Frameworks nutzen kann. Jeden Script-Teil, den ich im Dokument vor Einbindung der Bibliothek nutzen möchte, umschließe ich einfach mit $(function(){ … mein Script … }).

Dies ist die Kurzform von $(document).ready(function() { … mein Script … }) bzw. jquery(document).ready(function() { … mein Script … }) und wartet auf das vollständige Laden des Dokuments im Browser, um anschließend die Funktion mit „mein Script“ auszuführen.

Die Lösung

Die Gesamtlösung besteht aus drei Teilen im HTML Dokument. Im <head> der Webseite wird die Funktion $ definiert, die einfach das übergebene Argument (also jeweils die function() { … mein Script … }) in einem Array zwischenspeichert.

<head>
...
  <script>var $jqc=[];var $=(f)=>{$jqc.push(f)}</script>
...
</head>

Übrigens steht der Javascript code (f)=>{$jqc.push(f)} für eine abgespeckte Variante von function (f) { $jqc.push(f) }.

Siehe auch Dokumentation Javascript

Anschließend können nun mehrfach (oder einmal) Scripte in der o.g. jquery Notation eingefügt werden.

...
<body>
...
  <script>
    $(function(){
      ... mein Script mit beliebiger jquery Nutzung ...
    });
  </script>
...

Wenn jquery.js bereits geladen wäre, würde unsere Funktion warten, bis auch das Dokument vollständig geladen wäre. Anschließend würde es dann direkt ausgeführt werden. In unserer Lösung wird die Funktion nun dank dem ersten Teil bis zum dritten und letzten Teil zwischengespeichert.

...
  <script src="//code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
  ...
  <script>for(var f in $jqc){$jqc[f]();}</script>
</body>
...

Hier wird nun die jquery Bibliothek eingebunden und geladen. Anschließend führt das Inline Script unsere zwischengespeicherten Funktionen nacheinander aus.

Wir führen die gepuderten Funktionen unmittelbar vor dem Ende des HTML Inhaltes aus. Daher brauchen wir auch nicht mehr auf das Fertigladen des Dokumentes zu warten.

JQuery per async laden

Die o.g. Lösung wird für die meisten Webprojekte vollkommen ausreichen. Wer aber jetzt unbedingt noch jquery per „async“ laden möchte, kann dies unter Nutzung des „onload“ Events machen. Zur Realisierung ersetzen wir einfach den dritten Teil der Lösung wie folgt.

...
<script onload="for(var f in $jqc){$jqc[f]();}" async src="//code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
...

Hierbei werden die zwischengespeicherten Funktionen ausgeführt, nachdem jquery.js geladen wurde und dadurch automatisch das „onload“ Event getriggert wurde.