Im heutigen Türchen möchte ich euch eine interessante Extension vorstellen, deren Einsatz sich für wohl jede TYPO3-Installation lohnt: scriptmerger.
Nachdem ich den Autor Stefan Galinski (Webentwickler bei domainFACTORY) auf der T3UXW09 kennen lernen durfte und wir uns zusammen an einer Backend-Integration versucht haben, habe ich mich vor einigen Tagen selbst ausführlich mit der Nutzung von scriptmerger im Frontend befasst.
Wie man in der nebenstehenden Grafik schön sehen kann, hat sich die Optimierung durchaus gelohnt: ySlow bescheinigt der Seite jetzt Grade A (92 Punkte) anstatt Grade D (69 Punkte) und die Seite lädt wirklich spürbar schneller.
Was macht scriptmerger?
Im Wesentlichen führt es die folgenden drei Schritte jeweils für CSS- und JavaScript-Dateien durch:
- Minimierung: Entfernen von Kommentaren und Whitespaces, Umbenennung privater Variablen in kürzere
- Konkatenation: Zusammenfassen aller Dateien zu einer gemeinsamen Datei
- gzip-Komprimierung dieser Datei
Im Optimalfall ergibt sich dann jeweils ein HTTP-Request für das Stylesheet und einer für JavaScript. Durch die Minimierung und besonders durch die gzip-Komprimierung wird die zu ladende Dateigröße stark verringert (im Beispiel um den Faktor 5,9). Beides zusammen ergibt durch den Wegfall zahlreicher Requests und durch Effekte wie TCP’s Slow-Start eine gewaltige Verringerung der Ladezeit.
Um das Rad nicht neu zu erfinden baut scriptmerger für diese Arbeit auf den beiden erprobten PHP-Projekten Minify (für den CSS-Part) sowie JSMin+ (für den JavaScript-Part) auf.
Da wir uns für die Einbindung von jQuery über Google entschieden haben, benötigen wir einen zweiten JavaScript-Request. Häufig dürfte die Datei aber bereits im Browsercache liegen.
Installation und Konfiguration
Im Extension-Verzeichnis befindet sich die Datei example.htaccess. Ist der erste Dateiteil ein guter Tipp für sinnvolles Caching von Grafiken im Browser, so ist der zweite Teil bei der Nutzung von gzip essentiell und muss in die eigene .htaccess übernommen werden (sofern nicht vom Server-Admin selbige Regel für *.gz.* existiert):
<FilesMatch "\.gz\.(js|css)"> <IfModule mod_headers.c> Header set Content-Encoding gzip </IfModule> </FilesMatch>
Scriptmerger erzeugt die komprimierten Dateien mit den Endungen .gz.css bzw. .gz.js. Damit die Dateien dann auch on-the-fly vom Browser entpackt werden, ist das Setzen des Content-Encoding-Headers notwendig. Hierzu wird das Apache-Module mod_headers benötigt, das aber im Normalfall überall verfügbar sein sollte.
Nach der Installation der Extension ist noch das TypoScript-Template Scriptmerger einzubinden, welches folgendes (vereinfachtes) Setup liefert:
plugin.tx_scriptmerger { css { minify { enable = 1 ignore = \.min\. } compress { enable = 1 ignore = \.gz\. } merge { enable = 1 ignore = } } javascript { minify { enable = 1 ignore = \?,\.min\. } compress { enable = 1 ignore = \?,\.gz\. } merge { enable = 1 ignore = \? } } } |
Über die enable-Anweisungen lassen sich die einzelnen Teilfunktionen deaktivieren, sowie über ignore einzelne Dateien ausschließen (durch Angabe eines Dateinamenmusters als Regexp-Ausdruck, also Sonderzeichen escapen!).
Fehlersuche
Meiner Erfahrung nach geht geht nun erstmal nicht mehr viel, besonders was JavaScript betrifft 🙂
Oben gezeigte Einstellungen (enable/ignore) sind bei der Fehlersuche sehr hilfreich. Zunächst gilt es, die entsprechende Quelldatei, die für die Funktionalität zuständig ist, zu lokalisieren. Neben einem scharfen Blick auf die Datei sollte sie auch auf (Syntax-)Fehler hin untersucht werden (CSS-Validator bzw. JSlint). Beispielsweise führt ein fehlendes } am Dateiende zu keinen Auffälligkeiten, nach einer Konkatenation wird das Stylesheet ab diesem Punkt zu Recht falsch interpretiert.
Die JS-Minimierung hingegen ist im Bezug auf Fehleranfälligkeit nochmal komplexer, da die Syntax deutlich lockerer ist. So führen beispielsweise fehlende Semikolons am Ende einer Datei nach der Konkatenation und Minimierung oft zu Fehlern. Es empfiehlt sich der Einsatz von <strong>firebug</strong>, um diesen Fehler auf die Schliche zu kommen.
Mit etwas Zeitaufwand findet man aber meist die Problemquellen und auch irgendeine Lösung. Im Zweifel wird das betreffende Script eben durch ignore ignoriert und nicht minimiert – am weitaus wirkungsvollsten ist ohnehin die gzip-Kompression. Teilweise kann es bei Inkompatibilität mit JSmin+ auch helfen, das JavaScript mit einem anderen Packer zu packen und mit dateiname.min.js einzubinden. Gemäß der Ausschlussmaske wird es dann bei der Minimierung übergangen.
Änderungen an den Quelldateien werden von scriptmerger natürlich nur dann mit einbezogen, wenn eine Seite neu generiert wird. Es ist also nach jeder Änderung nötig, den Cache zu leeren oder während der Entwicklungsphase im Setup config.no_cache = 1 zu setzen.
Das i-Tüpfelchen
Für ein möglichst schnelles Rendering der Seite ist es ratsam, sämtliches JavaScript kurz vor das schließende </body>-Tag zu verlagern.
Seit TYPO3 Version 4.3 ist es mittels page.includeJSFooter möglich, auch auf sauberem Wege JavaScript in den Body einzubinden. Zuvor war dies nur durch Hooks und str_replace()-ähnliche Konstrukte möglich.
Jedoch wird sämtliches Body-JavaScript vom scriptmerger standardmäßig nicht angefasst, da dieser Vorgang sehr fehleranfällig ist. Durch Setzen von
plugin.tx_scriptmerger.javascript.parseBody = 1 |
wird nun aber auch dieser Bereich optimiert. Aufpassen muss man dabei aber auch, dass jetzt auch das Inline-JS zusammengefasst und minimiert wird. Hier ist ggf. nochmals eine Nachkorrektur erforderlich bzw. notwendig, den Code erst auszuführen, wenn das DOM fertig aufgebaut ist (z.B. mit $(document).ready() bei jQuery).
Fazit
Mit scriptmerger steht ein tolles Werkzeug bereit, um TYPO3 automatisch zusammengeführte und komprimierte Stylesheet- sowie JavaScript-Dateien generieren zu lassen. In der Regel ist die Installation mit einigen Nacharbeiten verbunden und sollte somit natürlich nicht im Live-Betrieb erfolgen. Am Ende wird man (bzw. die Besucher) aber auch dafür gebührend belohnt.
Durch die „Nachbearbeitung“ hat man nun aber auch die Möglichkeit, sein CSS/JS sinnvoll in viele Dateien aufzuteilen, ohne eine Unmenge weiterer Requests zu erzeugen. Trotz langer Expires-Header stellen nun auch alte Versionen im Browsercache kein Problem mehr da: Änderungen an den Dateien führen zu geänderten Dateinamen, die dann zwangsläufig neu geladen werden. Ein manuelles Anpassen der Referenz in TYPO3 entfällt.
Fehlerreports sowie Verbesserungsvorschläge nimmt Stefan gerne auf der Forge-Projektseite entgegen.