WordPress: Performance serverseitig verbessern ohne Plugins

Achtung! Dieser Artikel ist älter als ein Jahr. Der Inhalt ist möglicherweise nicht mehr aktuell!

Gestern habe ich meine Securitybetrachtung veröffentlich. Heute kommt Teil 2: Die (serverseitige) Performanceoptimierung ohne Plugins.

Vorraussetzung auch hier: Zugriff auf die vHost– oder .htaccess-Datei.

Wie bewertet man Performance

Die Performance von Webseiten bewerte ich, indem ich die Zeit messe bis die Seite komplett dargestellt wird. Dabei achte ich nicht auf Qualität des HTML oder ob ein oder mehrere JavaScript-Dateien nachgeladen werden und wo diese im Quellcode stehen, da diese „Fehler“ sich in der Renderzeit niederschlagen. Kurz gesagt: Für mich zählt das reine Ergebnis.

Flaschenhälse

Im Internet gibt es viele davon:

Bei der Optimierung muss man also auf viele Sachen achten. Vieles davon hängen gar nicht so sehr mit WordPress zusammen, sondern eher wie die Ressourcen genutzt und verteilt werden.

Optimierung des Webservers

Kompression

Wie funktioniert die Kompression im Browser

Fast alle gängigen Browser können mit gzip-Kompressierten Inhalten umgehen. Ob ein Browser Kompression unterstützt und welche Algorithmen er kann wird beim Request im HTTP Header „Accept-encoding“ definiert. Mein Browser frägt zum Beispiel so an:

Host: blog.veloc1ty.de
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Cache-Control: max-age=0

Den entsprechenden Header habe ich mal hervorgehoben. Mein Browser kann also gzip (Hinweis: Deflate wird in gzip genutzt).

Die Kompression von Text (wie CSS und JavaScript) ist sehr effektiv. Ich habe mal eine Passwort Datei gefunden, die gezippt 8 MB hatte und extrahiert über 4 GB hatte.

Binärdateien wie Bilder und andere Medien kann man hingegen schlecht komprimieren. Eventuell kommt es sogar zu einem Qualitätsverlust.

Durch die Kompression von Text verringert man drastisch die übertragene Datenmenge, was einen Flaschenhals in der Performance optimiert.

Änderungen an der vHost-Datei

Von Haus aus komprimiert der Apache Webserver nicht. Normalerweise ist das Modul schon installiert muss aber erst noch über

a2enmod deflate

aktiviert werden.

Danach definiert man MIME-Typen, die komprimiert werden sollen und auf welchem Level. Pro Zeile wird ein Type definiert. Meine Einträge sehen zum Beispiel so aus:

<VirtualHost *:80>
 [...]
 DeflateCompressionLevel 9
 AddOutputFilterByType DEFLATE text/plain
 AddOutputFilterByType DEFLATE text/html
 AddOutputFilterByType DEFLATE text/xml
 AddOutputFilterByType DEFLATE text/css
 AddOutputFilterByType DEFLATE text/js
 AddOutputFilterByType DEFLATE image/svg+xml
 AddOutputFilterByType DEFLATE application/xml
 AddOutputFilterByType DEFLATE application/xhtml+xml
 AddOutputFilterByType DEFLATE application/rss+xml
 AddOutputFilterByType DEFLATE application/javascript
 AddOutputFilterByType DEFLATE application/x-javascript
 [...]
</VirtualHost>

Das wäre es auch schon gewesen. Ich möchte nochmal explizit darauf hinweise, dass binäre Dateien wie PNG und JPEG nicht komprimiert werden. Wenn noch ein anständiges Linux darunter ist steigt die CPU Last nicht sonderbar an, da nach dem ersten aufrufen und komprimieren die Dateien im RAM ( damit meine ich den Diskcache ) abgelegt werden.

Nach einem Reload des Apache Webserver kann man in den Antwortheadern schon das Ergebnis sehen. Mir diesem cURL Befehl rufe ich meine Hauptseite auf:

curl -I -H 'Accept-Encoding: gzip, deflate' http://blog.veloc1ty.de

und habe danach diese Ausgabe:

HTTP/1.1 200 OK
Date: Fri, 25 Jul 2014 18:47:07 GMT
Server: Apache
X-Pingback: http://blog.veloc1ty.de/xmlrpc.php
Powered by: veloc1ty
Are you: reading this?
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: sameorigin
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html; charset=UTF-8

Im Antwortheader wird mein Webbrowser nun darauf aufmerksam gemacht, dass es sich um gzip komprimierten Inhalt handelt.

Genauerer Test des Ergebnisses

Um die Kompression richtig zu testen schaut man sich am besten die übertragene Datenmenge an. Firefox bietet sich dafür an. Der Einfachheit halber benutze ich aber cURL.

Laden der Seite ohne Kompression:

veloc1ty@pc:~$ curl -s -w "Size: %{size_download} bytes\n" http://blog.veloc1ty.de -o /dev/null
Size: 47787 bytes

Laden der Seite mit  Kompression:

veloc1ty@pc:~$ curl -s -H "Accept-encoding: gzip,deflate" -w "Size: %{size_download} bytes\n" http://blog.veloc1ty.de -o /dev/null
Size: 10611 bytes

Im Vergleich sieht man: 47787 bytes gegen 10611 bytes. Das ist eine Kompression von ca. 78%.  Ziemlich happig. Der nächste „Trick“ nutzt noch den Festplattenspeicher des Clients.

Caching von statischen Ressourcen

Bei Cache denken viele Webmaster/Webseitenbetreiber an Caching vom CMS System. Wir können aber auch den Cache des Clients nutzen. Dort legt man statische Ressourcen wie Bilder, JavaScript und CSS Code.

Beim Rendern bemerkt der Browser, dass er zum Beispiel ein JavaScript braucht und würde ohne Caching dieses vom Webserver herunterladen. Wir können den Browser aber anweisen das JavaScript lokal im Cache abzulegen und dies dann von der Festplatte laden.

Wie funktioniert der lokale Cache

Im HTTP Header Expires kann man eine Ablaufzeit für diese Ressource definieren. Ich benutze dafür eine Woche. Ein Antwortheader beim anfragen eines Bildes sieht dann zum Beispiel so aus:

Expires: "Fri, 01 Aug 2014 19:17:23 GMT"

Der Browser frägt nach der Datei erst wieder nach dem obigen Datum. Genau genommen frägt er schon danach, und zwar mit einem „If-modified since„-Header, woraufhin der Webserver mit einem „304 Not modified„-Header Antwortet.

Die paar übertragenen Bytes machen das Kraut nicht fett, da nicht das komplette Bild (mit mehreren Kilobyte) immer und immer wieder neu geladen wird.

Änderungen an der vHost-Datei

Apache2 hat das Modul zwar meistens schon dabei, jedoch nicht aktiviert. Dies macht man nachträglich mit diesem Kommando:

a2enmod expires

Nach einem Reload kann der Webserver auch damit umgehen. Wie bei der Kompression muss man dem Apache aber erst sagen, was alles beim Client gecached werden soll.

Achtung Achtung: Anders als bei der Kompression ist es nicht sinnvoll dynamische Inhalte zu cachen. Damit meine ich HTML. JavaScript und CSS können hingegen Problemlos gecached werden, da diese sich nicht so schnell verändern.

Folgendes trägt man in der vHost-Datei ein:

<VirtualHost *:80>
 [...]

 ExpiresActive on

 # Text
 ExpiresByType text/css "access plus 1 week"
 ExpiresByType text/javascript "access plus 1 week"
 ExpiresByType text/js "access plus 1 week"
 # Binary
 ExpiresByType image/x-icon "access plus 1 week"
 ExpiresByType image/png "access plus 1 week"
 ExpiresByType image/jpg "access plus 1 week"
 ExpiresByType image/gif "access plus 1 week"
 ExpiresByType image/jpeg "access plus 1 week"

 [...]
</VirtualHost>

Hier sollte man sämtliche, sich selten verändernden Ressource/MIME-Types eintragen, die die Homepage ausliefert. Bei mir sind das alos das JavaScript, CSS und Bilder.

Die Syntax ist selbsterklärend. Eine Woche ist ein guter Wert.

Bei einem bevorstehenden Templatewechsel sollte man das Cachen von JavaScript und CSS ausschalten, damit es später zu keinen Problemen kommt.

Firefox prüft auch vor dem Ablauf des Caches mit dem oben genannten „If-modified-since“-Header, ob sich die Ressource zwischenzeitlich geändert hat. Wie sich andere Browser verhalten weis ich leider nicht.

Testen des Ergebnis

Nach einem Reload kann man das Ergebnis prüfen. Diesmal leider nicht mir cURL. Der Firefox macht daraus ein schönes Bild.

Startseite_Cacheanalyse

Analyse des Cachingverhaltens mit dem Firefox

Man sieht sehr schön, dass das HTML nicht gecached wird, und das von 19 Anfragen 12 aus dem Cache kommen. Mehr Speed geht kaum.

Ich muss gestehen: Das Caching von JavaScript habe ich noch nicht so richtig hinbekommen. Aber ich arbeite daran.

Fazit

Mit Kompression und Caching kann man sehr viel erreichen und viele Flaschenhälse optimieren. Am Anfang habe ich pro Seitenaufbau ca. 2,4 Sekunden gebraucht, bis die Seite komplett angezeigt wird. Nun sind es im Durchschnitt nur noch wenige Millisekunden.

Weitere Optimierung

Ein schneller Server und eine gute Anbindung ans Internet sind hilfreich. Man sollte nicht beim billigsten Anbieter kaufen/mieten.

Es gibt nur noch einen Punkt, den man nicht durch den Webserver optimieren kann: Zusammenfassung des JavaScript- und CSS-Codes in eine einzelne Datei um Anfragen zu minimieren. Dazu benötigt man dann ein Plugin.

Weitere Optimierung sind dann nur noch über Analyse des Quellcodes möglich. Ein nützliches Tool stellt Google mit Google’s PageSpeed Insights bereit. Ein Blick lohnt sich auf jeden Fall.


Du hast einen Kommentar, einen Wunsch oder eine Verbeserung? Schreib mir doch eine E-Mail! Die Infos dazu stehen hier.

🖇️ = Link zu anderer Webseite
🔐 = Webseite nutzt HTTPS (verschlüsselter Transportweg)
Zurück