Asset-Hashing mit gulp und WordPress
Ich bastele ja wieder mehr, das hatte ich mir schließlich vorgenommen. Dieser Tage habe ich eine Kleinigkeit umgesetzt, die ich schon lange auf dem Plan hatte.
Damit meine Besucher in Zukunft immer die richtige HTML-CSS-Javascript-Kombination ausgespielt bekommen, versehe ich die entsprechenden Dateiennamen in Zukunft mit einem kryptischen Hash, der sich aus dem Inhalt der Datei berechnet. Statt barabalgerstle.css
wird nun zum Beispiel barabalgerstle-50aa08a0.css
ausgespielt.
Die Problematik entsteht dadurch, dass ich zwar Einfluss auf das serverseitige Caching des HTML-Markups habe und dieses jederzeit verwerfen kann, gleichzeitig aber aus Performance-Gründen die Zeiten für das Caching der CSS- und Javascript-Dateien für den Browser der Benutzer sehr hoch eingestellt sind. So kann es zu unschönen Nebeneffekten kommen. Zum Beispiel wenn mein Server neues HTML zum Benutzer schickt, dort im Browser aber noch das alte CSS aus dem Cache des Computers geladen wird. Dann sieht die Seite "kaputt" aus. "Lade einfach die Seite noch ein paar Mal neu!" wird dann gerne als Tipp gegeben.
Damit das in Zukunft auch funktioniert, ohne dass man auf seine Tastatur einhämmert, müssen zwei Dinge passieren.
Hashwert ermitteln und einbauen
Das war der einfachere Teil des Ganzen. Ich benutze den Taskrunner gulp in der Entwicklung und natürlich bin ich nicht der Erste, der vor diesem Problem steht. Mit Hilfe des Plugins gulp-hash ist das in meinem Fall eine einzeilige Änderung. Einfach das .pipe(hash())
vor dem Schreiben der Sourcemaps einfügen. Im Falle des CSS-Tasks sieht das so aus:
...
.pipe(hash()) // insert before sourcemaps to rename those too
.pipe(sourcemaps.write('./'))
...
WordPress den neuen Dateinamen beibringen
Darüber habe ich tatsächlich ein bisschen länger gegrübelt. Normalerweise sind die Dateinamen in WordPress hart verdrahtet, mit einem sich ständig ändernden Hash kann das CMS nicht umgehen. Am Ende war die Lösung dann aber auch ziemlich einfach. Ich schrieb mir eine einfache Hilfsfunktion, die anhand einer Vorgabe den wirklichen Dateinamen aus dem Dateisystem ausliest.
/**
* Returns the dynamically generated filename of an asset.
* It is retrieved by a given pattern (e.g. '/dist/barabalgerstle-*.css').
* Make sure that the pattern only matches one file.
*
* @param $pattern
*
* @return string
*/
function bg_get_hashed_filename( $pattern ) {
$files = glob( get_stylesheet_directory() . $pattern );
$filename = basename( $files[0] );
return $filename;
}
Mit Hilfe von glob finde ich alle Dateien die zum übergebenen Namens-Muster passen. Hierbei ist darauf zu achten das Muster spezifisch genug zu wählen, dass man nur eine Datei findet. Für meine Zwecke und vermutlich auch die meisten anderen Einsätze ist das völlig ausreichend. basename filtert dann aus dem kompletten Pfad nur den Dateinamen, der dann schließlich zurückgegeben wird.
Die Hilfsfunktion benutze ich nun einfach an den Stellen, wo ich vorher einen festen Dateinamen stehen hatte. Und fertig ist das Asset-Hashing mit gulp und WordPress.