Der folgende Beitrag ist ein Gastbeitrag von Pascal Klau, einem selbst beschriebenen Trainee-Webentwickler aus Deutschland, der mit WordPress, Gulp und neuerdings auch VueJS und Webpack arbeitet.
Auf meiner Reise, Webtechnologien zu lernen, bin ich auf die Bedeutung von Caching gestoßen. Es ist ziemlich wichtig für die Performance von Webseiten. Ich bemerke auch manchmal, dass, wenn eine Datei geändert wurde und man die Seite neu lädt, der Browser immer noch die alte Version verwenden kann (wegen des Caches). Es gibt eine Lösung!
Hashes brechen Caches
Durch das Hinzufügen eines Hashs zum Dateinamen denkt der Browser, es handelt sich um eine völlig andere Datei. Somit wird der "Cache gebrochen". Wenn sich beispielsweise die Datei `main.3hZ9.js` in `main.8a3s.js` ändert, wird der Browser sie definitiv neu herunterladen. Diese Umbenennung kann automatisch von Task-Runnern durchgeführt werden.
Für uns, die WordPress verwenden, gibt es jedoch ein Problem. Sie müssen die Dateien *namentlich* manuell enqueuen, aber Sie können den zufällig generierten Hash-Wert nicht kennen.
wp_enqueue_script('main', get_template_directory_uri() . '/js/main.3hZ9.js', array('jquery'), null, true);
Hashes mit Gulp hinzufügen
Bevor wir uns mit dem WordPress-Problem befassen, hier ist, wie man Hashes hinzufügt.
Da ich Gulp verwende, war gulp-hash sehr nützlich. Wenn Sie Grunt verwenden, gibt es Entsprechungen.
// ES5
var gulp = require('gulp'),
hash = require('gulp-hash');
var options = {
hashLength: 4,
template: '<%= name %>.<%= hash %><%= ext %>'
};
gulp.src('./js/**/*.js')
.pipe(hash(options))
.pipe(gulp.dest('build'));
// ES6 + Gulp 4
import gulp from 'gulp'
import hash from 'gulp-hash'
let options = {
hashLength: 4,
template: '<%= name %>.<%= hash %><%= ext %>'
};
export function hashing() {
return gulp.src('./js/**/*.js')
.pipe(hash(options))
.pipe(gulp.dest('build'))
};
const dev = gulp.series(hashing);
export { dev };
export default dev;
Die WordPress-Lösung
Hier ist, wie wir die gehashten Dateien automatisch enqueuen können! Der Trick ist, dass wir den Hash-Namen nicht kennen müssen, PHP wird die Datei trotzdem finden.
Zuerst bereiten wir uns darauf vor, das Dateisystem im Verzeichnis, in dem sich unser Asset befindet, zu durchsuchen.
function enqueue_files() {
$dirJS = new DirectoryIterator(get_stylesheet_directory() . '/js');
}
Nun durchlaufen wir alle Dateien und filtern nach denen, die auf `.js` enden.
foreach ($dirJS as $file) {
if (pathinfo($file, PATHINFO_EXTENSION) === 'js') {
}
}
Abhängigkeiten benötigen in WordPress einen Namen, also können wir diesen vom Dateinamen ableiten. "main" wäre besser als "main.3hZ9" (weil es sich nicht ändert), damit wir den Hash für den Enqueue-Namen entfernen können.
foreach ($dirJS as $file) {
if (pathinfo($file, PATHINFO_EXTENSION) === 'js') {
$fullName = basename($file); // main.3hZ9.js
$name = substr(basename($fullName), 0, strpos(basename($fullName), '.')); // main
}
}
In WordPress kann jede Asset, die Sie enqueuen, Abhängigkeiten benötigen. Sie deklarieren diese selbst, indem Sie ein Array davon an die Enqueue-Funktion übergeben. Hier prüfen wir die Datei und fügen bei Bedarf Abhängigkeiten hinzu.
foreach ($dirJS as $file) {
if (pathinfo($file, PATHINFO_EXTENSION) === 'js') {
$fullName = basename($file);
$name = substr(basename($fullName), 0, strpos(basename($fullName), '.'));
switch($name) {
case 'main':
$deps = array('vendor');
break;
default:
$deps = null;
break;
}
}
}
Alles zusammen jetzt!
Wir haben jetzt alles, was wir brauchen, um das Asset zu enqueuen, also hier ist alles zusammen.
foreach ($dirJS as $file) {
if (pathinfo($file, PATHINFO_EXTENSION) === 'js') {
$fullName = basename($file);
$name = substr(basename($fullName), 0, strpos(basename($fullName), '.'));
switch($name) {
case 'main':
$deps = array('vendor');
break;
default:
$deps = null;
break;
}
wp_enqueue_script( $name, get_template_directory_uri() . '/js/' . $fullName, $deps, null, true );
}
}
Für CSS-Dateien funktioniert es genauso, außer der leicht unterschiedlichen WP-Enqueue-Funktion.
Was ist mit PHP filemtime?
Mit WordPress können Sie in der Enqueue-Funktion einen Cache-breaking URL-Parameter mit filemtime hinzufügen. Er fügt jedes Mal einen Zeitstempel hinzu, wenn Sie die Datei ändern.
$file = get_template_directory_uri() . '/js/main.js'
wp_enqueue_script( 'main', $file, null, filemtime($file), true );
// => [...]/main.js?1203291283
Warum verwende ich diese Technik nicht?
Ich bündele JavaScript-Dateien in `main.js` und `vendor.js` (in meinem Fall mit Webpack). Wenn ich `main.js` bearbeite, ändert sich auch der Zeitstempel für `vendor.js`. So würde es jedes Mal heruntergeladen werden, ohne dass sich etwas ändert.
Hashes hingegen bleiben gleich.
Fazit
Jetzt können Sie Hashes dynamisch zu Dateien hinzufügen, wenn sie sich ändern, über Gulp. Und Sie können diese Dateien in WordPress enqueuen, ohne den neuen Dateinamen kennen zu müssen.
In den Argumenten von wp_enqueue_script ist die vierte Option eine Versionsnummer, die für Cache Busting gedacht ist. Warum nicht einfach die eingebaute Funktionalität nutzen? Was ist der Vorteil dieses Ansatzes?
Hallo Chris,
Sie möchten den Hash nicht jedes Mal manuell bearbeiten, wenn Sie die Datei speichern. Lassen Sie PHP das erledigen.
Sie könnten dafür PHP filemtime verwenden.
Aber der Grund, warum es vielleicht nicht das ist, was Sie wollen, wird am Ende des Artikels genannt. :)
Ich habe genau dasselbe gedacht...
Zustimmung; anstelle des Zeitstempels den On-the-Fly-Hash als "Version" verwenden. Ein wenig intensiv, je nach Datei/Server, aber man könnte die Hashes immer zwischenspeichern und Punkte für Ironie sammeln.
Ich verwende einfach die Build-Version, die ich dynamisch geändert habe und die im Theme definiert ist, dann verwendet das wp_enqueue_script Argument diese. Hat immer funktioniert, aber das ist auch eine coole Lösung.