Webseitenoptimierung Teil 2: Apache caching header
In Webseitenoptimierung Teil 1 habe ich mich mit der Beschleunigung des PHP-Codes beschäftigt. Das macht aber nur einen kleinen Teil der Seitenperformance aus.
Wenn man sich mal einen einen Breakdown der Seite mit Firebug für den Firefox oder HTTPwatch für den IE ansieht, stellt man fest, dass ein Großteil der Zeit damit verschwendet wird weitere HTTP-Requests zu stellen.
In den meisten Fällen handelt es sich dabei um Elemente wie CSS, JavaScript oder Bilder, welche sowieso schon im Cache des Browsers liegen. Die meisten ändern sich ja auch nur selten, aber der Browser muss nachfragen, ob sich das Element verändert hat oder eben nicht.
Hier mal ein Beispiel von meiner Seite
Host: www.schnuckelig.eu
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.1) Gecko/2008071420 Iceweasel/3.0.1 (Debian-3.0.1-1)
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
If-Modified-Since: Fri, 09 May 2008 22:33:57 GMT
If-None-Match: "39d0567-2fc-cb273f40"
Cache-Control: max-age=0
Das ist ein typisch unnötiger Request, welcher an den Server gestellt wird. Der Browser hat das Element bereits im Cache und fragt den Server, ob sich das Element seit dem 9. Mai geändert hat (If-Modified-Since-Header).
In der Antwort des Servers sehen wir, dass das eben nicht der Fall ist.
Date: Fri, 19 Sep 2008 19:42:23 GMT
Server: Apache/2.2.3 (Debian) DAV/2 PHP/5.2.0-8+etch11 mod_perl/2.0.2 Perl/v5.8.8
Connection: Keep-Alive
Keep-Alive: timeout=15, max=100
Etag: "39d0e17-2e7-cae36600"
Expires: Sun, 19 Oct 2008 19:42:23 GMT
Cache-Control: max-age=2592000
Der Server antwortet mit einem 304 (Not modified), dennoch hat das ganze in meinem Fall 272 ms gedauert.
Das ist natürlich nicht so viel, doch rechnet man mal alle Elemente zusammen sind das schnell mal ein paar Sekunden.
Wenn ich also dem Browser mitteilen möchte, dass er das Element für einen gewissen Zeitraum aus dem Cache nehmen soll ohne den Server überhaupt danach zu fragen, dann setze ich ich einfach ein Expires- und Cache-Control-Header.
Dabei hilft uns mod_expire und wir brauchen lediglich ein paar Einstellungen zu unserer Apache-Configuration hinzuzufügen.
ExpiresActive On
ExpiresDefault "access plus 300 seconds"
Das tragen wir entweder in der globalen Configuration des Servers ein oder nur für einen virtuellen Host.
Der Expire-Header wird damit aktiviert und für alle Inhalte erstmal auf 300 Sekunden in der Zukunft gesetzt. Das ist zwar schon ganz nett und wir könnten da natürlich auch einen viel längeren Zeitraum eintragen, aber wäre es nicht nett die einzelnen Elemente unterschiedlich zu behandeln? Bilder können vielleicht länger gecacht werden als CSS oder umgekehrt.
Auch das geht mit mod_expire mit der ExpiresByType-Anweisung. Innerhalb einer Directory-Direktive kann ich für die einzelnen Typen verschiedene Direktiven setzen oder aber auch global, ganz wie ich mag.
ExpiresByType text/html "access plus 1 day"
ExpiresByType text/css "access plus 1 day"
ExpiresByType text/javascript "access plus 1 day"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 day"
Man sieht also, dass ich Bilder für einen Monat cachen lasse und CSS nur für einen Tag.
So kann ich mir schon mal viele zusätzliche Requests sparen und die Seite lädt deutlich schneller, zumindest für Besucher die wiederkommen oder mehr als eine Seite aufrufen.