JavaScript- und CSS-Dateien parallel downloaden

Um den HTML-Code schlank zu halten, doppelten Code zu vermeiden und Browser-Caching optimal einsetzen zu können, lagern viele Entwickler JavaScript- und CSS-Code in eigene Dateien aus und referenzieren diese Dateien anschließend im HTML-Code mit dem <script>- bzw. <link>-Tag. Doch sollte einiges beachtet werden.

Zuerst ist zu sagen, dass auf CSS-Dateien stets im <head> der Seite referenziert werden sollte und auf JavaScript am Ende des Bodys. Das ist deshalb gut, weil der Browser dann sofort alle CSS-Regeln hat und sofort mit der Formatierung der HTML-Elemente beginnen kann. Ansonsten wartet der Browser mit dem Rendering der Seite bis alle CSS-Dateien geladen sind.
JavaScript-Dateien sollten aus dem Grund direkt vor </body> eingefügt werden, da mit JavaScript HTML-Elemente erzeugt werden können, z.B. durch document.write() oder document.createElement(). Dadurch wird der HTML-Baum verändert. Deshalb muss der Browser mit dem Rendern des folgenden HTML-Codes warten bis die JavaScript-Datei geladen ist (denn der Browser weiß ja vorher nicht, was in der JS-Datei gemacht wird).
Mehr dazu, warum CSS im Head eingebunden werden sollte, gibt es bei Google Page Speed und im Yahoo Developer Network.

Nun kommt es aber manchmal vor, dass man noch einzelne kleine Code-Anweisungen nicht auslagern kann, beispielsweise wenn per PHP noch eine Variable eingefügt werden muss. Man hat dabei zwei Möglichkeiten:

  1. Dynamische CSS- bzw. JS-Datei per PHP-Script erstellen und Variable als GET-Parameter übergeben
  2. CSS- bzw. JS-Code mit dem Parameter direkt in den HTML-Code unterbringen

zu 1.: Diese Variante ist sehr schlecht, da mit der Änderung des Parameters sich der Dateiname der Ressource ändert. Dadurch muss die gesamte Datei erneut geladen werden, denn der Browser kann nicht auf die Datei aus dem Browser-Cache zugreifen.
zu 2.: erstmal noch kurz, was genau mit parametrisierten CSS- und JS-Anweisungen gemeint ist:

<style type="text/css">
.klasse { width: <?php echo $breite; ?> }
</style>
<link rel="stylesheet" href="restliches_CSS.css" type="text/css" />
 
<script type="text/javascript">
var elemente = "<?php implode(",",$elementeArray); ?>";
</script>
<script src="restliches-Javascript.js" type="text/javascript"></script>

Diese Variante ist besser, da der größte Teil der Ressource aus dem Browser-Cache geladen werden kann. Aber es gilt folgendes zu beachten:
Wie oben gesagt, beginnt der Browser erst mit dem Rendering, sobald er alle CSS-Dateien und -regeln geladen hat. Deshalb sollten die parametrisierten CSS-Regeln, die im HTML-Code stehen möglichst auch im <head> stehen. Es ist aber zu beachten, dass JavaScript-Code zwischen 2 externen Ressourcen die Parallelisierung verhindert. Deshalb sollten stets alle externen JS-Dateien direkt hintereinander eingebunden werden. Erfolgt zwischen den einzelnen Referenzierungen zu CSS-Dateien oder JS-Dateien ein JS-Befehl, kann der Download nicht parallel erfolgen.

Beispiel (ganz schlecht):

<head>
<link rel="stylesheet" type="text/css" href="stylesheet1.css" />
<script type="text/javascript" src="scriptfile1.js" />
<script type="text/javascript" src="scriptfile2.js" />
<link rel="stylesheet" type="text/css" href="stylesheet2.css" />
<link rel="stylesheet" type="text/css" href="stylesheet3.css" />
</head>

Hier wird der Download der Dateien stylesheet2.css und stylesheet3.css blockiert, weil die JS-Dateien dazwischen den HTML-Baum verändern könnten.

Beispiel (auch schlecht):

<head>
<link rel="stylesheet" type="text/css" href="stylesheet1.css" />
<script type="text/javascript">
 document.write("Hello world!");
</script>
<link rel="stylesheet" type="text/css" href="stylesheet2.css" />
<link rel="stylesheet" type="text/css" href="stylesheet3.css" />
</head>

Zuerst wird die Ausführung des Inline-Style-Befehls durch stylesheet1.css verzögert. Anschließend verhindert die Inline-Anweisung wiederum, dass die Stylesheets parallel heruntergeladen werden können.

Beispiel (gut):

<head>
<link rel="stylesheet" type="text/css" href="stylesheet1.css" />
<link rel="stylesheet" type="text/css" href="stylesheet2.css" />
<link rel="stylesheet" type="text/css" href="stylesheet3.css" />
<script type="text/javascript">
   document.write("Hello world!");
</script>
</head>

Zuerst alle externen Ressourcen einbinden. Alle werden parallel heruntergeladen. Anschließend das Inline-Script. Natürlich sollte das JavaScript möglichst weit unten in den Body geschrieben werden, da es genauso das Laden von Bildern verzögert.
Alle Beispiele stammen von hier.

Folgende Tipps kann ich demzufolge geben:

  • alle CSS-Datei-Referenzierungen per <link>-tag in den <head> direkt hintereinander schreiben
  • alle <script>-Tags direkt vor </body> (wenn möglich)
  • möglichst keine JS-Anweisungen (inline oder extern) zwischen CSS-Referenzierungen
  • keine JS-Inline-Anweisungen zwischen mehreren Referenzierungen auf JS-Dateien

Interessant in diesem Zusammenhang ist auch der Beitrag von Rakesh Pai namens Download JavaScript Files in Parallel. Er geht dabei auf das HTML-Attribut defer ein, das schon lange im Internet Explorer und seit Version 3.1 auch im Firefox implementiert ist. Damit umgeht man die Blockierung anderer Ressourcen durch JavaScript, da das defer einfach dem Browser mitteilt, dass das Script nicht sofort geladen werden muss, sondern erst, wenn der gesamte Body geladen ist. Dadurch brauchen dann andere Ressourcen nämlich auch nicht blockiert zu werden. Dadurch bräuchten die JS-Referenzierungen dann auch nicht mehr zwingend ganz am Ende des Bodys stehen.

Jan hat 152 Beiträge geschrieben

14 Kommentare zu “JavaScript- und CSS-Dateien parallel downloaden

  1. Phate sagt:

    Hallo,
    zugegeben war das hier komplett alter Hut für mich aber ist ja nicht tragisch.

    Wenn man sich für den Firefox das Add-On Firebug installiert, gibts noch ein paar Addon-Addons. Unter anderem das hier mal irgendwann vorgestellte YSlow, aber auch „Page Speed“ von Google:
    http://code.google.com/intl/de-DE/speed/page-speed/download.html

    Mithilfe von FireBug + YSlow + PageSpeed habe ich zB bei meiner Page so ziemlich alles verbessert was ohne großen Arbeitsaufwand realisierbar war. Performancegewinn von gefühlten 40-50%.

  2. Rakesh Pai sagt:

    Sorry, I don’t speak German, so my comment is in English.

    Actually, the defer attribute is not required in IE for the script download to happen in parallel. I know my original code had it, but it didn’t make a difference if I removed it, so I removed it. 🙂

    I’m glad you liked the script. Just be sure to get the latest version from my blog if you need to use it.

  3. schlauberger sagt:

    das ist ja ein blog hier, da wird man doch direkt rausgelöscht wenns den star programmierern nicht passt.

    als ob man hier auch nur irgendetwas selber rausgefunden hätte…

  4. Jan sagt:

    @schlauberger: Was wurde denn gelöscht? Ich habe nix gelöscht. Eventuell hat der Spamfilter zugeschlagen, aber da habe ich jetzt auf Anhieb auch nix gefunden.

  5. Ingo sagt:

    Nun, das mit dem JavaScript am Ende des Body kommt aber auch auf das Script drauf an. Ein FrameBrecher funktioniert dort nämlich nicht. Der zerschießt dann auch die Frames von Adsense.

  6. bmueller sagt:

    Nicht alle Javascripte können vor dem positioniert werden. z.B. JQuery und co. laufen den nicht und die sind nun mal sehr groß weshalb es sich dort lohnen würde.

  7. Pingback: Julian Pustkuchen

Eine Antwort schreiben

Ihre E-Mail-Adresse wird nicht veröffentlicht. Benötigte Felder sind markiert mit *

You may use these HTML tags and attributes: <a href=""> <blockquote cite=""> <pre lang=""> <b> <strong> <i> <em>