SideBarMenu

Pakete und Kompression von JavaScript

Motivation

Für wartbares JavaScript sind u.a. folgende Punkte entscheidend:

Dokumentation

Unbestreitbar sollte JavaScript-Code genau wie jeder andere Code an Ort und Stelle kommentiert sein/werden können. Idealerweise müsste literate programming möglich sein („When was the last time you spent a pleasant evening in a comfortable chair, reading a good program?").

Dem steht allerdings das Problem gegenüber, dass mit unserem gegenwärtigen System jedes Dokumentationsbyte auch an alle Stud.IP-Nutzer ausgeliefert wird. Gute Dokumentation kann recht ausführlich sein und es spricht alles dagegen, statt der gegenwärtigen ~350 kB (ohne vorhandene Dokumentation) eines Tages ~700 kB (mit zukünftiger Dokumentation) auszuliefern.

Anzahl der Dateien

Wenn man Code wartbar halten will, macht es Sinn, Code-Teile, die nichts miteinander zu tun haben, nicht in einer riesigen, sondern lieber in mehreren separaten Dateien vorzuhalten.

Dem steht aber der Wunsch gegenüber, möglichst wenig Requests an den Server zu schicken (siehe z.B. http://code.google.com/speed/page-speed/docs/rtt.html). In der jüngeren Vergangenheit was das dramatischer (http://www.browserscope.org/?category=network) als es jetzt ist. Dennoch macht man alles richtig, wenn man möglichst wenig Dateien sendet.

Komprimierung

Anders als bei z.B. PHP-Code macht es bei JavaScript einen Unterschied, wie man seinen Code formattiert, da jedes einzelne Zeichen über die Leitung geht. Selbstverständlich würde man niemals uneingerückten Code auf einer Zeile schreiben, nur um die Zahl der Bytes zu minimieren. Andererseits machen sich selbst einfache Formen der Komprimierung (z.B. Einrückung und Kommentare entfernen) in Hinsicht auf die Performance bezahlt. Mit vorhandenen Tools wie dem YUI-Compressor[1], Google-Closure-Compiler[2] oder dem Uglifier[3] läßt sich viel gewinnen. Die Komprimierung des Webservers (z.B. Apaches mod_deflate) setzt dem ganzen das Sahnehäubchen auf (ist aber natürlich alleine für sich nicht so gut wie die genannten Tools.)

1: http://developer.yahoo.com/yui/compressor/ 2: http://code.google.com/p/closure-compiler/ 3: https://github.com/mishoo/UglifyJS

Spezifischer Code

Nicht jeder JavaScript-Code muss auf jeder Seite verfügbar sein. Es ist z.B. unnötig, die Studienbereichzuordnung auch auf Wiki-Seiten zu laden. Derzeit bleibt uns nicht anderes übrig, als alles in einer Datei und damit auf jeder Webseite zu haben. Schöner könnte es sein, wenn man das für jede Seite (natürlich nur in einem gewissen Rahmen siehe "Anzahl der Dateien") selbst entscheiden könnte.

Fazit

Der Stud.IP-Nutzer mag (aus Performance-Gründen) JavaScript, das in wenigen Dateien ohne unnötige Zeichen komprimiert ausgeliefert wird.

Der Stud.IP-Entwickler mag (aus Wartbarkeitsgründen) JavaScript, das in vielen Dateien mit viel Whitespace und Dokumentation versehen ist.

Stud.IP-Implementation

Glücklicherweise kann man in Stud.IP mit geringem Aufwand beides haben:

1.) JavaScript wird in sinnvolle Dateien aufgeteilt und kann dort beliebig formatiert und dokumentiert werden.

2.) Diese Dateien in sinnvolle Pakete zusammen, die dann je nach Bedarf der Seite geladen werden.

Die Pakete werden in der Datei config/assets.yml formuliert:

compress: true
javascripts:
  jquery: &jquery
    - javascripts/jquery/jquery-1.7.js
    - javascripts/jquery/jquery-ui-1.8.14.custom.min.js
    - javascripts/jquery/jquery.metadata.js
    - javascripts/jquery/jquery.placehold-0.3.js
    - javascripts/jquery/validator.min.js

  base:
    - *jquery
    - javascripts/underscore.js
    - javascripts/l10n.js
    [...]

  raumzeit:
    - javascripts/raumzeit.js

  smileys:
    - javascripts/smiley.js

3.) In Stud.IP wird per Default das Paket "base" eingebunden. Weitere Pakete können im PHP-Code so hinzugefügt werden:

[code] <?= PageLayout::addSqueezePackage("raumzeit") ?> [/code]

4.) Entsprechend des Modus, in dem sich die Stud.IP-Version befindet (Produktiv- oder Entwicklermodus), werden die JS-Pakete unterschiedlich ausgegeben:

a.) Im Entwicklermodus will man alle Möglichkeiten zum Debugging haben. Wenn man beispielsweise die Pakete "base" und "raumzeit" eingebunden hat, ergibt sich folgende Ausgabe:

<script src="assets/javascripts/jquery/jquery-1.7.js"></script>
<script src="assets/javascripts/jquery/jquery-ui-1.8.14.custom.min.js"></script>
<script src="assets/javascripts/jquery/jquery.metadata.js"></script>
<script src="assets/javascripts/jquery/jquery.placehold-0.3.js"></script>
<script src="assets/javascripts/jquery/validator.min.js"></script>
<script src="assets/javascripts/underscore.js"></script>
<script src="assets/javascripts/l10n.js"></script>
<script src="assets/javascripts/raumzeit.js"></script>

Es werden lediglich Tags generiert, die auf die unkomprimierten Einzeldateien verweisen. Performance ist in diesem Zusammenhang nebensächlich.

b.) Im Produktivmodus will man optimale Performance erreichen. Mit denselben Paketen "base" und "raumzeit" ergibt sich dazu folgendes:

<script src="assets/squeezed/base.js"></script>
<script src="assets/squeezed/raumzeit.js"></script>

Die darin verlinkten Dateien enthalten den konkatenierten und anschließend komprimierten Code aller JS-Dateien, die zum entsprechenden Paket gehören. Der Inhalt einer solchen JS-Paket-Datei würde zum Beispiel so aussehen:

(function(){var a=window;a.hello=function(a,b){a.alert("Hello, "+a)}})();

Wenn man ein Stud.IP-Release installiert hat, wurden die entsprechenden Dateien bereits erzeugt. Nimmt man später Änderungen an den eigentlichen JS-Dateien (also beispielsweise an "assets/javascripts/raumzeit.js") vor, müssen die Dateien erneut erzeugt werden. Dazu gibt man auf der Kommandozeile innerhalb der Stud.IP-Installation den folgenden Befehl ein:

make build

Damit tatsächlich komprimierte (und nicht nur konkatenierte) JS-Paket-Dateien herauskommen, muss auf dem Rechner Java installiert sein, da das Kompressionstool dies benötigt.

Letzte Änderung am 21.08.2012 11:09 Uhr von mlunzena.