In meinem Vortrag über Web Performance Optimization auf der Web Tech Conference erwähnte ich mod_pagespeed als super funktionierende automatische Lösung um Requests von CSS und JavaScripts zu reduzieren und so Webseiten schneller zu machen. Doch dann fiel mir beim Betrachten der Statistiken von www.codecentric.de auf, dass mod_pagespeed gar nicht korrekt funktionierte.
Eigentlich sollten mehrere CSS Dateien zu einer zusammengefügt werden, doch ich fand diese Anweisungen im HTML:
1<link rel='stylesheet' id='login-css' href='wp-admin/css/login.css,qver=20110610.pagespeed.cf.ZqFxSZoD1J.css' type='text/css' media='all'/> 2<link rel='stylesheet' id='colors-fresh-css' href='wp-admin/css/colors-fresh.css,qver=20110703.pagespeed.cf.ldpZyBlEpG.css' type='text/css' media='all'/>
Ok, das ist zumindest schonmal die von Pagespeed verarbeitete, d.h. minifizierte, Version der CSS Dateien. Ohne Pagespeed sähe die Stelle so aus:
1<link rel='stylesheet' id='login-css' href='wp-admin/css/login.css?ver=20110610' type='text/css' media='all'/> 2<link rel='stylesheet' id='colors-fresh-css' href='wp-admin/css/colors-fresh.css?ver=20110703' type='text/css' media='all'/>
Diese zwei Zeilen sollte eigentlich von dem Filter „combine_css“ zu einer Zeile zusammengefasst werden. Die Dokumentation beschreibt aber, dass dies in der Tat nicht immer passiert:
The CSS Combine filter operates within the scope of a „flush window“. Specifically, large, or dynamically generated HTML files may be „flushed“ by the resource generator before they are complete. When the CSS combiner encounters a flush, it will emit all CSS combinations seen up to the point of the flush. After the flush, it will begin collecting a new CSS combination.
und
IE Directives containing CSS links form a „barrier“ for the CSS combiner. Multiple CSS elements found before an IE directive are combined together immediately before the IE directive. Multiple CSS elements found after are also combined, but the combination does not span across the IE directive, as that would affect the order that the browser sees the CSS elements.
Jedoch ist hier weder eine IE Direktive, noch sind die beiden Zeilen nicht im gleichen „Flush-Fenster“. Warum funktioniert es also nicht?
Es gibt tatsächlich eine, leider nicht dokumentierte, weitere Bedingung:
Tags können nur zusammengefasst werden wenn dadurch keine Information verloren geht.
Welche Information dies in diesem Beispiel wäre, kann man relativ leicht feststellten: Die beiden Identifier „login-css“ und „colors-fresh-css“ könnten dann nicht weiterexistieren. Es wäre ja denkbar, dass diese Identifier von JavaScript Code verwendet würden, um das CSS zu modifizieren oder andere Dinge zu tun.
Aber wo kommen diese IDs eigentlich her? Brauchen wir sie? Und wie können wir sie loswerden?
WordPress besitzt eine Funktion namens „wp_enqueue_style “ mit der Plugin- und Themeentwickler Styles dynamisch in den head-Bereich einfügen können. wp_enqueue_style nimmt als ersten Parameter ein sogenanntes handle. Genau dieses handle verwendet WordPress um sie als ID zu verwenden.
In der Regel braucht man die ID nicht, da es keinen standardmäßig vorhandenen Code gibt, der über die ID der Styles an die Style-links geht. Und selber wird man wahrscheinlich auch keinen Code schreiben, der IDs auf Style link Tags benötigt. WordPress fügt die ID der vollständigkeit halber an.
Damit mod_pagespeed die CSS Dateien zusammenfügen kann, muss sie jedoch weg. Das ganze geht am einfachsten über WordPress Filter. Es gibt nämlich einen Filter der für den fertigen Style Link Tag aufgerufen wird: „style_loader_tag“.
1function remove_style_id($link) {
2 return preg_replace("/id='.*-css'/", "", $link);
3}
4add_filter('style_loader_tag', 'remove_style_id');
Dies würde dann in folgendem HTML resultieren:
1<link rel='stylesheet' href='wp-admin/css/login.css?ver=20110610' type='text/css' media='all'/> 2<link rel='stylesheet' href='wp-admin/css/colors-fresh.css?ver=20110703' type='text/css' media='all'/>
Und es wird nun in der Tat korrekt zusammengefasst:
1<link rel="stylesheet" type="text/css" href="wp-admin/css/login.css,,qver==20110610+colors-fresh.css,,qver==20110703,Mcc.35EZfaJvqU.css.pagespeed.cf.I5odih6TFY.css" media="all"/>
Abschließend bleibt noch zu erwähnen, dass die gleiche Einschränkung auch für „media“ gilt. Bietet man Styles für verschiedene Medien an, können diese ebenfalls nicht zusammengefasst werden. Hier sollte man entsprechend prüfen ob man die Unterscheidung braucht, alle CSS den richtigen media-Typ haben und gegebenenfalls das media Attribut entfernen.
Weitere Beiträge
von Fabian Lange
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Fabian Lange
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.