WordPress Themes optimieren. Mit Node.js schneller werden

So kann es gehen: Das neue Blog ist fertiggestellt. Das gekaufte Template sieht schick aus. Die Inhalte sind eingestellt. Eigentlich könnte die Site live gehen. Aber dann…

… sieht man sich die Ergebnisse des Browser-Plugins http://yslow.org/ an. Und wird leicht blaß im Gesicht. Denn das Plugin vergibt eine 5 in Schulnoten für die HTTP-Requests. Aua. Das hat gesessen!

Vor allem ist die Diagnose eindeutig: das neue WordPress Template bindet zu viele CSS und JavaScript-Dateien ein. Warum ist das schlecht? Geschwindigkeit ist nicht nur ein Faktor im Google Ranking. Die Besucher suchen das Weite, wenn die Site zu lange lädt.

Im konkreten Fall wurden 11 CSS und 19 JavaScript-Dateien eingebunden. Das ist zu viel. Und zwar eindeutig zu viel. Zu allererst: für die Anpassungen benötigen wir ein Child Theme. Wie dies angelegt wird, beschreibt der WordPress Codex.
Änderungen sollten nie im Original-Theme erfolgen. Und dann kann es losgehen:

Welche Funktionen benötige ich überhaupt?

Zunächst sollte überprüft werden, welche Funktionalitäten das Theme überhaupt haben soll. Themes sind immer auf viele Anwendungsfälle ausgelegt und viele Optionen werden konkret nicht benötigt.

Wichtig ist das gezielte Aussortieren. Brauche ich auf einer einzigen Seit wirklich mehrere Slider, Parallax Effekt, Scroll-Effekte, Lightboxen, Counter und Google Maps? Das ist alles ganz schön viel. Als erstes suche ich nur die Effekt aus, die ich auch wirklich benötige. Weniger ist mehr und damit wirkt die Seite auch nicht mehr so überladen.

Dazu sehe ich mir den Quelltext im Browser an sowie functions.php im Parent-Theme. In meinem Fall ist das eine riesige Liste von Files, die nacheinander eingebunden werden, wp_enqueue_style() für die CSS Files und wp_enqueue_script() für die Skripte.

Die Lösung: Dateien zusammenfassen

Damit wissen wir, wo die Einbindung erfolgt und was getan werden sollte. Das empfiehlt yslow: entweder die Files per Content-Delivery-Network einbinden oder zusammenfassen (concat) und verkleinern.
Das Parent-Theme in WordPress darf allerdings nicht modifiziert werden. Gibt es je ein Update des Themes, werden unsere Änderungen überschrieben.

Also wissen wir jetzt, was zu erledigen ist: Die CSS- und JS-Dateien dürfen nicht mehr im Parent-Theme eingebunden werden. Stattdessen verkleinern wir die Dateien und binden sie in unserem Child-Theme ein.

An der Stelle händisch alle CSS und JavaScript Files zu suchen, bedeutet einiges Arbeit. Und diese Arbeit muss nochmal erledigt werden, sobald sich im Eltern-Template etwas ändert. Und in einem halben Jahr habe ich wahrscheinlich auch vergessen, welche Files ich zusammengefasst hatte. Keine gute Idee. An der Stelle kommt Node.js zur Rettung:

Mit Node.js und Grunt den Prozess automatisieren

Besser ist es, sich einmal mehr Arbeit zu machen und einen Task-Runner aufzusetzen. Damit können bei den nächsten Änderungen die minfifizierten Files per Knopfdruck erzeugt werden.

Ich selbst nutze das Node.js Modul grunt als Task Runner. Andere Task Runner wie gulp tun es aber sicherlich auch. Unsere Tasks sind für die Javascript files concat und uglify (minifizieren). Für die CSS-Files concat und css-minify. Der Task jshint wird nicht benötigt. Schließlich geht es nicht um meinen eigenen Sourcecode, der hier eingebunden wird.

Also los. Auf der BASH ins Child-Theme Directory wechseln. Anschließend mit npm init ein neues Projekt anlegen. Und mit npm install --save-dev grunt-cli wird der Task Runner Grunt installiert. Grunt ist ein Task Runner, der Aufgaben abarbeitet. Dazu brauchen wir jetzt Module, die ausgeführt werden sollen: zusammenfassen (concat), minifizieren von JS (uglify) und von CSS (css-minify). Der Task „clean“ löscht Files (dazu gleich mehr). Und watch überwacht Files (auch dazu gleich mehr).


npm install grunt-contrib-uglify --save-dev
npm install grunt-contrib-cssmin --save-dev
npm install grunt-contrib-uglify --save-dev
npm install grunt-contrib-concat --save-dev
npm install grunt-contrib-watch --save-dev
npm install grunt-contrib-clean --save-dev

Diese Node-Pakete sind jetzt vorhanden und sollten in package.json unter „devDependencies“ auftauchen.
Jetzt benötigen wir noch ein Gruntfile.js, das nach dem Rezept der Grunt-Docs erstellt wird. Also: leeres Files namens Gruntfile.js anlegen. In meinem Fall sieht das so aus:

module.exports = function(grunt) {

grunt.initConfig({
concat: {
options: {
// define a string to put between each file in the concatenated output
separator: ';'
},
homepagejs: {
// no slick.js, jquery.magnific-popup.min.js, jquery.magnific-popup-init.js
src: [
'../parallel-pro/js/navigation.js',
'../parallel-pro/js/parallax.js',
'../parallel-pro/js/bootstrap.js',
'../parallel-pro/js/scrollreveal.js',
'../parallel-pro/js/waypoints.js',
'../parallel-pro/js/jquery.counterup.js',
'../parallel-pro/js/smooth-scroll.js',
'../parallel-pro/js/header.js',
'js/main.js',
],
dest: 'js/concat-home.js'
},
},
uglify: {
homepage: {
files: {
'js/home-min.js': ['js/concat-home.js']
}
}
},
cssmin : {
target: {
files: {
'css/parallel-theme.min.css': [
'../parallel-pro/css/bootstrap.css',
'../parallel-pro/css/multi-columns-row.css',
//'../parallel-pro/css/font-awesome.css',
'./css/font-awesome-temp.css',
'./style.css',
],
}
}
},
clean : ['js/concat-home.js'],
watch: {
files: ['style.css','js/main.js'],
tasks: ['default']
}
});

grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-watch');

grunt.registerTask('default', ['replace','concat','uglify','cssmin','clean']);
};

Ich habe in dem File in den Kommentaren auch die Namen der Files hinterlegt, die nicht eingebunden werden. Damit erspare ich mir Arbeit beim Abgleich bei Änderungen im Parent Template. Noch ein Hinweis: die Reihenfolge ist entscheidend. Bei CSS-Files ist die Reihenfolge wichtig, falls Definition überschrieben werden. Als letztes File binden wir daher das Child Theme CSS File ein.
‚./style.css‘
Das style.css des Parent Themes muss nicht extra eingebunden werden, da es per export im Child eingebunden ist
@import url(„../parallel-pro/style.css“);

Die verkleinerten Files sind jetzt erstellt und können eingebunden werden. Das geschieht in functions.php. Zum einen wird mit remove_parent_scripts() die Einbindung im Parent-Theme komplett ausgehebelt. „name_of_function_in_parent_theme“ muss entsprechend ersetzt werden. Sollte es weitere Skript geben, etwa CDN-Einbindungen von Google Fonts, so müssen diese in unsere add_child_scripts() Funktion.


add_action('wp_enqueue_scripts', 'add_child_scripts', 100);
function add_child_scripts()
{

// minified files of parent and child. see Gruntfile.js
wp_enqueue_style('minified-parent-css', get_stylesheet_directory_uri().'/css/parallel-theme.min.css', array(), '1.0' );
wp_enqueue_script('minified-parent-home', get_stylesheet_directory_uri().'/js/home-min.js', array('jquery'), '1.0', true );

}
add_action( 'init', 'remove_parent_scripts');
function remove_parent_scripts() {
remove_action('wp_enqueue_scripts', 'name_of_function_in_parent_theme');
}

Das war es für das erste auch. Und. Erster Test im Browser. Es funktioniert. Fast! Das CSS-File von Font Awesome findet die Schriften nicht, die noch im Parent Theme liegen. Das ist auch logisch: Die Pfade sind dort relativ angegeben. Die einfachste Lösung: Schriften oder fehlende Grafiken einfach ins Child Theme zu kopieren. Alternativ dazu gibt es ein Plugin, das dies eigentlich erledigen kann https://github.com/Ideame/grunt-css-urls.

Fazit

Was hat das ganze gebracht? Einiges. Und zwar sind jetzt nur noch 8 JavaScript- und 4 CSS-Dateien eingebunden. Inklusive der minifizierten Skripte und CDN-Ressourcen. Allerdings stammen diese entweder von WordPress selbst oder von Plugins. Eine Optimierung hier bringt Risiken mit sich: wird das Plugin deaktiviert, bleibt das Skript trotzdem noch eingebunden, da Node.js ja nichts von WordPress-Backend-Einstellungen weiß.

Den eigentlichen Vorteil mit Grunt aber vielleicht zum Schluß: mit dem watch-Prozess kann ich jetzt an CSS und JavaScript-arbeiten und die Files werden automatisch kompiliert. Wie ich oben geschrieben hatte: der komplette Prozess muss nach jeder Änderung an CSS oder JavaScript Files im WordPress Child Theme erfolgen. Das erledigt ab jetzt grunt watch für uns. Und die Ladezeit der Site ist deutlich besser!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.