JavaScript-Komprimierung – Eine Gegendarstellung
Während es Blogs gibt, in denen kritische Kommentare nicht gerne gesehen sind, werden auf phphatesme sogar ganze Contra-Beiträge veröffentlicht, in diesem Fall zu dem Thema JavaScript-Komprimierung.
Die provokante Aussage war, sehr kurz gefasst: JavaScript-Komprimierung sei eine Lösung für ein Problem das man gar nicht hat.
Statt einer einfachen Gegenposition möchte ich – auch unter Zuhilfenahme der zahlreichen Kommentare – aufzeigen welche Gründe und Möglichkeiten es für eine Komprimierung gibt. Ein weites Feld und leider musste bereits während der Bearbeitung einiges aus Platzgründen wieder gestrichen werden.
Warum überhaupt Komprimierung?
Manche Webseiten liefern über 50 Grafiken oder Bilder, deren Gesamtvolumen problemlos den MegaByte-Bereich sprengen. Dazu noch ein gutes dutzend CSS-Dateien, ein paar IFrames und noch etwas Flash. Warum sollen da ausgerechnet ein paar kleine JavaScript-Dateien so problematisch sein?
Zum einen haben wir mit Web 2.0 und immer ausgefeilteren Oberflächeneffekten immer mehr und größere JavaScript-Dateien. Zum anderen ist das Ladeverhalten bei JavaScript-Dateien anders als beispielsweise bei Bildern, die erst nach dem Rendern der Seite parallel angefordert und geladen werden. Ich möchte hier auf einen Blogeintrag verweisen, der zwar ASP.NET behandelt, im ersten Teil aber das Ladeverhalten von JavaScript beispielhaft aufzeigt:
http://www.atashbahar.com/post/Combine-minify-compress-JavaScript-files-to-load-ASPNET-pages-faster.aspx
Nicht vergessen darf man, dass vor jedem “Seitenerlebnis” das geladene JavaScript noch interpretiert werden muss.
Die Komprimierung und Optimierung von JavaScript ist kein Luxus, sondern wird mit der stetigen Zunahme von Funktionalität und der Annäherung der Oberflächen an echte Applikationen noch mehr an Bedeutung gewinnen, damit die immer komplexeren Seiten trotzdem schnell angezeigt werden können.
Auch nicht vergessen darf man mobile Geräte die eben nicht mit DSL-Geschwindigkeit surfen. Grafiken können für eine schnellere Darstellung ausgeschaltet werden, viele Seiten sind ohne JavaScript aber nicht mehr funktional.
Manchmal ist der Platz, den man für sein JavaScript zur Verfügung hat auch aus ganz anderen, banalen Gründen begrenzt, wenn beispielsweise CMS-Systeme nur wenige hundert Bytes für ein Banner oder andere Seitenobjekte samt JavaScript erlauben und sprichwörtlich jedes Zeichen zählt.
Welche Anwendungsfelder gibt es?
“Butzi” hatte es in seinem Kommentar benannt: Obfuscating, Verkleinerung und serverseitig Kompression und Expire.
Obfuscating/ Verschleierung
JavaScript muss lokal vom Browser interpretiert werden. Deshalb ist es unsinnig zu glauben, man könne seinen Code so schützen, dass er irreversibel verschleiert werden kann. Sehr wohl aber kann man Hürden aufbauen in der Hoffnung, dass andere die den eigenen Code verwenden wollen oder aber Schwachstellen in der Seite suchen das Interesse verlieren und sich anderen Seiten zuwenden. Der Aspekt der Sicherheit sollte hier nicht unterschätzt werden.
- Änderung von Namen.
Namen lassen oft auf den Zweck von Code schließen. Werden Variablennamen verkürzt und verlieren damit ihre Bildhaftigkeit – ursprünglich nur um ein paar Bytes zu sparen – verschlechtert das die Lesbarkeit und die direkte Analysemöglichkeit durch andere. - Rückschlüsse auf dahinterliegendes PHP über Ajax-Aufrufe können so zumindest erschwert werden.
- Etwas banaler, aber nicht ganz ohne Bedeutung: Entfernung aller Kommentare. Kommentare wie “Ready to rumble…” oder “DAU-Kontrolle” mögen ganz putzig sein, nach außen dringen sollten sie in keinem Fall.
Reduzierung der übertragenen Datenmengen
Damit ist sowohl eine Reduzierung der übertragenen Dateien, als auch deren eigentliche Größe gemeint. Beide Ziele können sich widersprechen, im Zweifelsfall sollte aber die Reduzierung der Anzahl der Requests im Vordergrund stehen.
- Entfernen aller unnötigen Whitespaces. Mit einer guten IDE – empfehlen möchte ich natürlich Netbeans – kann ein lesbarer Zustand mit einem Klick wiederhergestellt werden.
- Frameworks sollten nur in einer Version und als kleinere Produktionsversion verwendet werden.
- Zusammenführung von externen JavaScript-Dateien in wenige, größere Dateien um die Anzahl der Requests zu verringern.
- JavaScript darf nicht doppelt vorhanden sein, das mag banal klingen, kommt in der Realität öfters vor – sei es durch das Kopieren ganzer Bereiche oder innerhalb von HTML-Seiten.
Serverseitige Kompression und Expire
Philip hatte es in seinem Kommentar ausgeführt: Serverseitig kann über den Apache die Kompression von Inhalten wie JavaScript aktiviert werden um die zu übertragende Datenmenge zu verringern.
Nach der Entwicklungsphase ändern sich die JavaScript-Dateien selbst nicht mehr und über den Server kann das Expire für JavaScript- und auch CSS-Dateien hoch gesetzt werden.
Zusammen mit den bekannten Caching-Möglichkeiten können hier eine Menge Bytes und Rechenzeit für schlechtere Zeiten gespart werden:
http://httpd.apache.org/docs/2.0/mod/mod_deflate.html und http://httpd.apache.org/docs/2.0/mod/mod_expires.html
Tools und Werkzeuge
Alle Theorie ist grau, dafür sind hier ein paar Links zu wichtigen Werkzeugen und Tools aufgeführt. Auch der etwas genauere Blick auf die Ausführungen auf diesen Seiten kann sich lohnen.
Der YUI Compressor. Ein Java-Programm und eine interessante Webseite mit weiterführenden Informationen.
http://developer.yahoo.com/yui/compressor/
Auch diverse Online-Versionen gibt es im Web: http://refresh-sf.com/yui/ oder http://yui.2clics.net/
Der Closure Compiler von Google. Die Konkurrenz zum YUI-Kompressor, auch ein Java-Programm. Google bietet einen “Closure Inspector” als Firebug Plugin um den erzeugten Code debuggen zu können.
http://code.google.com/intl/de-DE/closure/compiler/
Eine Online-Versionen ist unter http://closure-compiler.appspot.com/home zu finden.
Der JavaScript CompressorRater, ein Vergleich gängiger Komprimierer, inklusive Online-Komprimierung durch die Tools JSMin, Dojo shrinksafe, Packer (Version 3.1) und dem YUI Compressor (Version 2.4.2).
http://compressorrater.thruhere.net/
Javascript Compressor. Online-Komprimierung optional mit Base64 Kodierung und dem Verkürzen von Variablennamen.
http://javascriptcompressor.com/
CodeTrimmer ver 2.0 Beta, Online-Komprimierung und Downloadmöglichkeit, geschrieben in JavaScript.
http://www.twinhelix.com/javascript/codetrim/
Der JavaScript Optimizer. Ein Tipp von Jan. Maven-kompatibel, für JavaScript und CSS.
http://js-optimizer.sourceforge.net/
Übersicht über Tools zur CSS-Komprimierung, eigentlich fast off-topic an dieser Stelle, soll aber dennoch nicht unerwähnt bleiben.
http://www.drweb.de/magazin/10-online-werkzeuge-zur-css-komprimierung/
Nicht vergessen: Optimierung beim Programmieren!
Trotz aller Werkzeuge und Tools darf ein Entwickler die Optimierung und Performance seines Codes niemals anderen überlassen. Wer seinen Code unnötig aufbläht oder langsamen Code schreibt hat seine Hausaufgaben nicht gemacht – diese Art der Optimierung ist aber wieder ein ganz anderes Thema.
Hier noch eine Alternative zum Ladeverhalten Geschlächtsreifer Browser während der Paarungszeit: http://www.smashingmagazine.com/2009/07/19/how-to-automate-optimization-and-deployment-of-static-content/
In dem Post geht es um die Optimierung von Ladezeiten im allgemeinen also Bilder, CSS und JS als Helfendes tool ist das ruby script juicer genannt welches ebenfalls Whitespaces löscht und mehrere dateien zu einer zusammenfasst.
Viel spass beim lesen
Philipp
Vielleicht hab ich’s jetzt nicht ganz umrissen – aber unter „Gegendarstellung“ hatte ich spontan was anderes erwartet?
Nicht zu vergessen ist natürlich die PHP5-Lösung „minify“ (http://code.google.com/p/minify/) mit der sich JavaScript und CSS komprimieren lassen. Ein großer Vorteil die Dateien erst beim Abruf zu komprimieren (natürlich mit Caching, auch über Memcache möglich) liegt darin dass man in der Entwicklung keine zweite ordentlich formatierte Version der Dateien pflegen muss (wie es WordPress z.B. macht; man beachte hierzu /wp-includes/js/xxx.js und xxx.dev.js).
Durch das Gruppieren von Dateien in der Konfiguration kann man unter Anderem auch Abhängigkeiten auflösen und verhindern dass der Designer beispielsweise jQuery Plugins lädt und jQuery selbst vergisst.
Dank Caching und heute in der Regel leistungsfähigen Servern ist eine solche Lösung selbst bei größeren Seiten nicht als Bremsklotz spürbar und die Vorteile überwiegen meiner Meinung nach. Man hat mit „minify“ eine Lösung die sehr leicht eingerichtet werden kann und einem mehrere Schritte auf einmal abnimmt. Gruppieren, Komprimieren, Caching des Gesamtpakets.
@Steffkes – Ich auch, aber trotzdem recht interessanter Artikel. Danke an den Autor!
BITTE schreib‘ nicht „CMS-Systeme“
…wenn beispielsweise CMS-Systeme nur wenige hundert Bytes für ein Banner…
„Content Management System-Systeme“ 😉
Nichtsdestotrotz sehr interessant.
Gegendarstellung deshalb, da vor kurzem hier die Meinung vertreten wurde, dass JavaScript Komprimierung völlig überflüssig ist und nur ein Fall von premature optimization ist.
Hmm … Also einerseits ist die Reduzierung der JS-Gesamtgröße auch dafür da, um mobile Endgeräte mit langsamer Anbindung zu unterstützen, andererseits wird Komprimierung empfohlen. Jetzt frag ich mich schon: Frisst die Dekomprimierung auf dem schwachbrüstigen System den Gewinn durch die schnellerer Übertragung nicht möglicherweise wieder auf?
@KingCrunch:
Das was sich JavaScript-Compressor nennt, ist im eigentlichen Sinne kein komprimieren, es geht dabei nur darum durch eine Obfuskation den Code kürzer zu machen. Lokale Variablen innerhalb einer Funktion haben einige Zeichen, eben eine möglichst gute Bezeichnung, der Compressor geht nun hin und ersetzt den Namen durch einen deutlich kürzeren (a, b, c, …) und spart so einige Zeichen ein. Das gleiche mit Leerzeichen und noch mehr solcher Operationen, im Verhalten des JavaScript-Interpreters/Compilers ändert sich also nichts, bis auf deutlich weniger Code zu parsen, dementsprechend ist er weiterhin genauso schnell.
Das einzige, was das Laufzeitverhalten ändern könnte, wäre eine gzip-Kompression, da diese erst entpackt werden muss, aber gzip Stufe 1 ist fast in Realtime (de)komprimierbar und wird so kaum einen Einfluss haben.
Was man neben den von dir aufgeführten Punkten auch nicht unterschätzen sollte:
+ Werden mehrere JS Dateien eingebunden erhöht das uU die Latenz bis alle Dateien geladen sind. Das ist gerade wichtig wenn das Projekt international aufgestellt ist und Nutzung aus anderen Ländern zu erwarten ist. Ergo => JS/CSS Dateien jeweils zusammenfassen.
+ Die Größe der Daten ist nicht nur bei mobilen Geräten entscheidend, sondern ebenso bei einer international genutzten Applikation. Die Bandbreite ist nicht in allen Ländern so toll wie in DE.
Meine ganz persönliche meinung:
Komprimierung auf httpd ebene ja, source code „compression“ nein, und wenn dann nur wenn VORHER alle skripte in eine datei kopiert werden. eine große datei ist schneller übertragen (nochdazu komprimiert) als der handshack beim verbindungsaufbau wenn 10-20 dateien geladen werden müssen. (jquery & ein paar plugins sag ich nur..)
Zur einfacheren Handhabung kann das noch dazu bequem serverseitig per skript erledigt werden. (welches seinen output natürlich cachen sollte sonst ist der vorteil durch längere code execution wieder weg)
Im idealfall hat man für statische inhalte natürlich einen kleinen schlangen httpd (zb. lighttpd) der liefert das dann nochmal einen ticken schneller aus, aber in der heutigen zeit in der IP’s knapp sind wird man nicht immer eine eigene ip dafür bekommen. (anderer port wäre zwar möglich ist aber im geschäftsumfeld unpraktikabel). andere alternative ist zb. S3.
my2c
Ludwig
In dem Kontext finde ich Diffable ganz spannend:
http://www.stevesouders.com/blog/2010/07/09/diffable-only-download-the-deltas/
Zur Verwendung kann ich nix sagen, aber die Idee ist abgefahrn 🙂
>>>Entfernen aller unnötigen Whitespaces. Mit einer guten IDE – empfehlen möchte ich natürlich Netbeans – kann ein lesbarer Zustand mit einem Klick wiederhergestellt werden.
Wo finde ich den das in Netbeans?
@ragtek Source -> Format
ragtek: http://netbeans.org/
>> Sehr wohl aber kann man Hürden aufbauen in der Hoffnung, dass andere die den eigenen Code verwenden wollen oder aber Schwachstellen in der Seite suchen das Interesse verlieren und sich anderen Seiten zuwenden. Der Aspekt der Sicherheit sollte hier nicht unterschätzt werden. <<
hm, Security by Obscurity… der Aspekt der Sicherheit sollte dann wohl eher nicht *über*schätzt werden.