published on
tags: WordPress Cachify uberspace

Brotli Kompression mit Cachify nutzen

Update 24.06.2017: Die Programmdatei heißt nicht mehr bro, sondern brotli.

Cachify ist ein sehr gutes WordPress-Caching-Plugin, ursprünglich aus der Feder von Sergej Müller. Mit aktiviertem HDD-Cache speichert Cachify standardmäßig das generierte HTML ab und kmoprimiert diese noch mit gzip. Ein neuer, besserer Kompressionsalgorithmus ist Brotli von Google. Er wird aktuelle bereits von einigen Browsern unterstützt.

Die Cache-Dateien werden so nochmal um einiges kleiner als bei gzip (z.B. die Startseite einer meiner Webseiten: HTML 11,8KB, gzip 4,2KB, Brotli 3,6KB). Um möglichst gute Performance zu erreichen, kann man, wie es Cachify auch schon mit gzip macht, die HTML-Dateien bereits vor dem Aufruf komprimieren und ebenfalls auf der Festplatte zwischenspeichern.

Die folgende Anleitung setzt einen Zugriff per Kommandozeile auf den Server voraus, so wie er z.B. bei uberspace möglich ist, d.h. root-Rechte werden nicht benötigt.

Brotli kompilieren

Brotli muss zuerst selbst aus dem Quellcode kompiliert werden. Dazu müssen auf dem Uberspace folgende Befehle ausgeführt werden:

$ wget https://github.com/google/brotli/archive/master.zip
$ unzip master.zip
$ cd brotli-master/
$ ./configure && make
$ mv bin/brotli ~/bin/brotli
$ cd ..
$ rm master.zip
$ rm -r brotli-master/

Dadurch hat man eine ausführbare Datei brotli im PATH und kann diese nun verwenden.

Cache-Dateien automatisch mit Brotli komprimieren

Nachdem nun der Brotli-Kompressor vorhanden ist, brauchen wir noch ein Skript, was uns alle vorhanden HTML-Dateien in einem Verzeichnis (inkl. Unterverzeichnissen) mit Brotli komprimiert. Bereits komprimierte Dateien werden nicht noch einmal komprimiert. Zur Konfiguration muss der absolute Pfad zum Verzeichnis des Cachify-Caches in der Variablen CACHIFY gespeichert werden. Im Skript ist als Beispiel eine Konfiguration für einen uberspace angegeben, es müssen nur noch $USER und $DOMAIN mit den entsprechenden Werten ersetzt werden.

#!/bin/bash

CACHIFY="/var/www/virtual/$USER/$DOMAIN/wp-content/cache/cachify"

for x in `find $CACHIFY -type f -name '*.html'`; do
    if [ ! -f $x.br ]; then
        ~/bin/brotli --input $x --output $x.br
        chmod 644 $x.br
    fi;
done

Dieses Skript kann so eingerichtet werden, dass es mehrmals aufgerufen wird, z.B. per cron oder runwhen. Die Zeit ist dabei frei wählbar, das Skript sollte aber nicht zu selten laufen, damit neu angelgte Cache-Dateien auch irgendwann in Brotli komprimiert werden.

Cache leeren

Die Brotli-komprimierten Dateienen werden genauseo wie die anderen gecachten Dateien durch ein leeren des Cachify-Caches, egal ob über den Button in der Admin Bar oder beim Speichern einer Seite oder eines Artikels.1 Daneben gibt es auch noch das Script, das alle Brotli-komprimierten Dateien aus dem Cacheverzeichnis löscht:

#!/bin/bash

CACHIFY="/var/www/virtual/$USER/$DOMAIN/wp-content/cache/cachify"

for x in `find $CACHIFY -type f -name '*.html.br'`; do
    rm $x;
done

.htaccess anpassen

Natürlich muss anschließend noch die WordPress-.htaccess-Datei angepasst werden, damit die Brotli-Dateien auch an alle kompatiblen Browser (z.B. Firefox) ausgeliefert werden. Das originale .htaccess-Snippet muss dafür auch nicht groß erweitert werden. Zwei Dinge sind hinzugefügt worden: Der Brotli-Block unter dem Block zu gzip-Kompression und die neue RewriteCond %{HTTP:Accept-Encoding} !br im gzip-Block. Diese verhindert, dass ein Browser mit aktivem Brotli die gzip-Version erhält. So sieht dann der gesamte Block für eine meiner Websites aus ($USER und $DOMAIN wie immer ersetzen):

# BEGIN CACHIFY
<IfModule mod_rewrite.c>
	<IfModule mod_mime.c>
		# GZIP FILE
		RewriteCond %{REQUEST_URI} !^/wp-admin/.*
		RewriteCond %{REQUEST_METHOD} !=POST
		RewriteCond %{QUERY_STRING} =""
		RewriteCond %{HTTP_COOKIE} !(wp-postpass|wordpress_logged_in|comment_author)_
		RewriteCond %{HTTP:Accept-Encoding} gzip
		RewriteCond %{HTTP:Accept-Encoding} !br
		RewriteCond /var/www/virtual/$USER/$DOMAIN/wp-content/cache/cachify/https-%{HTTP_HOST}/%{REQUEST_URI}index.html.gz -f
		RewriteRule ^(.*) /wp-content/cache/cachify/https-%{HTTP_HOST}%{REQUEST_URI}/index.html.gz [L]

		AddType text/html .gz
		AddEncoding gzip .gz

		# BROTLI FILE
		RewriteCond %{REQUEST_URI} !^/wp-admin/.*
		RewriteCond %{REQUEST_METHOD} !=POST
		RewriteCond %{QUERY_STRING} =""
		RewriteCond %{HTTP_COOKIE} !(wp-postpass|wordpress_logged_in|comment_author)_
		RewriteCond %{HTTP:Accept-Encoding} br
		RewriteCond /var/www/virtual/$USER/$DOMAIN/wp-content/cache/cachify/https-%{HTTP_HOST}/%{REQUEST_URI}index.html.br -f
		RewriteRule ^(.*) /wp-content/cache/cachify/https-%{HTTP_HOST}%{REQUEST_URI}/index.html.br [L]

		AddType text/html .br
		AddEncoding br .br
	</IfModule>

    RewriteCond %{REQUEST_URI} /$
    RewriteCond %{REQUEST_URI} !^/wp-admin/.*
    RewriteCond %{REQUEST_METHOD} !=POST
    RewriteCond %{QUERY_STRING} =""
    RewriteCond %{HTTP_COOKIE} !(wp-postpass|wordpress_logged_in|comment_author)_
    RewriteCond /var/www/virtual/$USER/$DOMAIN/wp-content/cache/cachify/https-%{HTTP_HOST}%{REQUEST_URI}index.html -f
    RewriteRule ^(.*) /wp-content/cache/cachify/https-%{HTTP_HOST}%{REQUEST_URI}index.html [L]
</IfModule>
# END CACHIFY

Mit diesen kleinen Änderungen lassen sich für Nutzer aktueller Browser noch stärker komprimierte Dateien ausliefern, was die Ladezeit, vor allem auch in mobilen Netzen, etwas verkürzt. Derzeit ist auf meiner WordPress Website so wie hier beschreiben im Einsatz.

Die Scripts können natürlich auch auf andere Szenarien angewendet werden, z.B. auf die Komprimierung von statischen HTML-Seiten, CSS-Stylesheets oder JS-Dateien. Dafür müssen sie natürlich an den entsprechenden Einsatz angepasst werden. Vor allem das Löschen der komprimierten Dateien bei Veränderung des Originals dürfte sich nicht so einfach darstellen.


  1. Dies ist zumindest bei meiner Einstellung für die WordPress-Permalinks der Fall. ↩︎