Geschwindigkeit optimieren mit Adaptive Images

Von Luca

Schon zwei Monate vergangen seit ich am Blog geschraubt habe. Nachdem ich damals die Plugins Cachify, Crazy Lazy und Autoptimize neu eingesetzt habe, sind alle drei wieder rausgeflogen. Zwischendurch habe ich es wieder einmal mit W3 Total Cache probiert, aber dadurch wurde das Backend sehr zäh und ich hatte teilweise das Gefühl alles stockt. Vor etwa zwei Wochen habe ich von den Google Webmaster Tools öfters Mails bekommen, dass der Blog nicht erreicht werden konnte. Erst vermutete ich einen Fehler beim Server, aber inzwischen glaube ich, dass Cachify Schuld war. Während es für aktuelle Beiträge wunderbar funktionierte, führt es bei manchen älteren zu einem Fehler. Als ich mich selbst durchs Profil klickte wurde mir immer wieder eine leere Seite präsentiert.

Angeregt durch einen Austausch mit Martin Wolf auf Twitter habe ich mich gestern dran gemacht meine WordPress Installation weiter zu optimieren. Nachdem Code und Caching schon bisher gut liefen, blieben vor allem die Bilder, die bei mir bis zu 80% des Datenvolumen des Blogs ausmachten.

Bilddateien in der dem Display entsprechenden Größe: Adaptive Images

Bei responsive Designs frage ich mich immer wieder, wie weit sie neben dem Aussahen auch von der Funktion optimiert sind. Bei dem Theme Kiore Moana, das ich hier nutze werden Vorschaubilder genutzt, die über die gesamte Fenstergröße reichen. Ich lade meist direkt Bilder vom Lumia 1020 hoch, welche meist mehrere Megabyte groß sind. Diese werden dann auch auf mobilen Geräte geladen und per CSS auf vielleicht 10% ihrer Größe reduziert angezeigt. Doof. Lösungsversuche gibt es viele, oft muss man umständlich alle Bilder mehrfach hochladen und umständlich Regeln definieren.

Mit Adaptive Images von Matt Wilcox habe ich eine Lösung gefunden, die mir sinnvoll erscheint und relativ einfach umsetzbar ist. Der Server liefert je nach Endgerät (mobile im browser string) oder Cookie (Displaygröße) runtergerechnete Bilder aus, die für den nächsten Abruf am Server gecacht werden. Eine Anleitung dafür gibt es unter anderem bei elma Studio, an der ich mich neben dem readme orientiert habe.

Internal Server Error 500

adaptive-images.php auf den Server laden, ai-cache Ordner mit passenden Berechtigungen erstellen und JS einbinden war kein Problem. Aber als ich die .htaccess anpasste, gab es immer einen Internal Server Error 500. Da WP Supercache bereits zahlreiche Regeln in die .htaccess geschrieben hat, ging ich davon aus, dass es damit Probleme gibt. Diverse Suchen danach brachten leider kein Ergebnis. Erst als ich begann nach .htaccess Regeln rund um Bilder zu suchen, kam ich zu einer Lösung.

Die Rewrite Rules werden anscheinend so oft durchgegangen bis es kein Match mehr gibt. Das führt recht schnell zu Loops und das führt zu 500er Fehlern. Abhilfe schaffen Flags. [L] bedeutet Last und es wird danach nicht mehr erneut nach einem Match gesucht. [NC] sorgt dafür, dass das Match nicht case sensitiv gehandelt wird.

In meiner .htaccess steht nun folgender Block:
# BEGIN Adaptive Images
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} !/images/ [NC]
RewriteRule .(png|gif|jpe?g)$ adaptive-images.php [L,NC]
</IfModule>
# END Adaptive Images

Größen der ausgelieferten Bilder

In adaptive-images.php habe ich zwei Zeilen angepasst. Fotos, die ich unbearbeitet vom Handy nehme, haben eine Auflösung von 3072 × 1728. Das ist für meinen Desktop mit 2560×1440 um einiges zu groß. Daher habe ich bei 2560 begonnen und bin dann die häufigsten Auflösungen des letzten halben Jahres in der Statistik durchgegangen. Das Ergebnis ist den vom Skript vorgeschlagenen Werten sehr ähnlich:
$resolutions = array(2560, 1920, 1366, 1024, 768, 480);
Außerdem habe ich die Zeit, die das Bild vom Browser gecacht werden soll von 7 Tagen auf 31 erhöht.
$browser_cache = 60*60*24*31;

Weiteres Aufräumen

Lazy Load habe ich entfernt, um jquery nicht mehr zu benötigen. Mithilfe von BWP Minify lasse ich den Großteil der JavaScripte und CSS gar nicht bis zum Browser durch indem ich ich sie auf ‘forget’ gesetzt habe. Etwa das CSS vom Jetpack Subscribe Feature. Ich möchte, dass bereits angemeldete Personen weiterhin Beiträge per Mail bekommen, aber ich brauche das CSS nicht auf der Seite, weil ich es nirgends eingebunden habe.

In die .htaccess habe ich dann noch mehr gzip und browser caching gepackt. Hier dürfte sich vieles doppeln, weil die Plugins dies teilweise selbst übernehmen. Kann ich mich irgendwann einmal genauer damit auseinandersetzen. Für den Moment funktioniert es.

Speed nach Auflösung

Bisherige Größe mit Bildern in voller Auflösung: 3,5MB (alter Screenshot von gestern; für die restlichen habe ich den Browsercache abgedreht)

2560px: 2,3MB

1366px: 996KB

1024px: 927KB

480px: 306KB (musste etwas tricksen indem ich das Cookie manuell editierte, da ich die Bildschirmauflösung nicht weiter reduzieren konnte)

Für mobile Geräte sollter der Blog nun bis zu zehn Mal schneller laden. Aber auch Laptops und Tablets profitieren von den optimierten Bildern. Und ich muss mich in Zukunft nicht mehr darum kümmern, weil das Skript alles automatisch erledigt.

Nachteile

Dadurch dass die Bildgröße über die .htaccess auf einer niedrigen Ebene angepasst wird, haben Personen mit einem kleinem Display gar nicht die Möglichkeit größere Bilder anzufordern. Nicht einmal wenn sie die Bild-URL direkt im Browser aufrufen. Ich weiß auch noch nicht, wie die Google Bildersuche damit umgeht.

Edit: Auf Facebook wurde mir empfohlen als weitere Rewrite Condition den Google Image Bot einfach auszuschließen, damit dieser die Bilder weiterhin in voller Auflösung bekommt:
RewriteCond %{HTTP_USER_AGENT} !Googlebot-Image/1.0 [NC]

Die Bilder müssen für jede Größe angepasst werden, wenn sie nun noch nicht im Cache sind, kann das dazu führen, dass die Anfrage länger dauert, als wenn man die volle Größe geladen hätte. Da der Blog auf einem shared Webspace läuft, kann es auch passiern, dass das Skript in Zeit- oder Speicherbegrenzungen läuft und gar nichts ausgeliefert wird.