Dynamische Hashes in Dateinamen mit der Enqueue-Funktion von WordPress verwenden 

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

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.