Caching in WordPress

Hinweis: Die aktuelle Version 2.9.0.3 von HyperCache behebt die in diesem Artikel angesprochenen Kritikpunkte. Dank an den Autor des Plugins, Stefano Lissa, für das prompte Einpflegen des Patches.

Es gibt viele Möglichkeiten, die Performance einer Website zu verbessern. Neben der Optimierung von Bildern, HTML, JavaScripts und StyleSheets sowie Kompression ist sowohl browser- wie auch serverseitiges Caching (das Vorhalten von Daten in einem Zwischenspeicher) eine gute Option.

Auf dieser Website setze ich eine modifizierte Version des Hyper Cache Plug-Ins für WordPress ein. Für WordPress gibt es mehr als ein dutzend Caching-Plug-Ins, ich habe mich für dieses aufgrund seiner Einfachheit (es macht, was es soll, und nicht mehr) sowie der gefühlt guten Performance entschieden.

Ein paar kleinere und größere Kritikpunkte des Original-Plug-Ins (Version 2.8.9) gab es allerdings schon, die mich dazu veranlasst haben, das Plug-In leicht zu überarbeiten:

  • Das Browser-Caching wurde durch das Setzen von entsprechenden HTTP-Antwort-Headern deaktiviert. Meiner Meinung nach ein großes No-No. Eine bessere Option besteht darin, die maximale Browser-Cache-Verweildauer anhand der Differenz der in den Optionen des Plug-Ins festgelegten Ablaufzeitspanne und des Alters der serverseitig gecachten Datei festzulegen.
  • Bei Aktivierung der Kompression im Plug-in wurde nach der ersten Anfrage an eine Seite diese unkomprimiert ausgeliefert. Verschmerzbar, aber auch leicht zu ändern.
  • Der Last-Modified HTTP-Antwort-Header fehlte trotz Aktivierung in den Plug-In-Optionen bei jedem ersten ungecachten Seitenzugriff.
  • Und noch eine Kleinigkeit, die „304 Not Modified“ HTTP-Antwort sollte idealerweise so früh wie möglich im Code erfolgen, um nicht serverseitig unnötig Daten zu verarbeiten, die dann gar nicht gebraucht werden.

Zu guter Letzt hier die Code-Änderungen, welche die obigen Kritikpunkte beseitigen, im diff-Format gegen 2.8.9:

--- cache-2.8.9.php	Mon Apr 02 17:33:19 2012
+++ cache.php	Mon May 21 18:08:21 2012
@@ -91,6 +91,15 @@
     return;
 }

+if (array_key_exists("HTTP_IF_MODIFIED_SINCE", $_SERVER)) {
+    $if_modified_since = strtotime(preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]));
+    if ($if_modified_since >= $hc_file_time) {
+        header("HTTP/1.0 304 Not Modified");
+        flush();
+        die();
+    }
+}
+
 // Load it and check is it's still valid
 $hyper_data = @unserialize(file_get_contents($hc_file));

@@ -117,21 +126,12 @@
 }

 // It's time to serve the cached page
-if (array_key_exists("HTTP_IF_MODIFIED_SINCE", $_SERVER)) {
-    $if_modified_since = strtotime(preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]));
-    if ($if_modified_since >= $hc_file_time) {
-        header("HTTP/1.0 304 Not Modified");
-        flush();
-        die();
-    }
-}

-// Now serve the real content
+$maxage = $hyper_cache_timeout - $hc_file_age;
+header('Cache-Control: max-age=' . $maxage);
+header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $maxage) . " GMT");

 // True if user ask to NOT send Last-Modified
-header('Cache-Control: no-cache, must-revalidate, max-age=0');
-header('Pragma: no-cache');
-header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
 if (!$hyper_cache_lastmodified) {
     header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $hc_file_time). " GMT");
 }
@@ -195,7 +195,7 @@
     if ($hyper_redirect) {
         if ($hyper_cache_redirects) {
             $data['location'] = $hyper_redirect;
-            hyper_cache_write($data);
+            $buffer = hyper_cache_write($data);
         }
         return $buffer;
     }
@@ -233,13 +233,13 @@

     if (is_404()) $data['status'] = 404;

-    hyper_cache_write($data);
+    $buffer = hyper_cache_write($data);

     return $buffer;
 }

 function hyper_cache_write(&$data) {
-    global $hc_file, $hyper_cache_store_compressed;
+    global $hc_file, $hyper_cache_lastmodified, $hyper_cache_store_compressed, $hyper_cache_timeout;

     $data['uri'] = $_SERVER['REQUEST_URI'];

@@ -247,12 +247,21 @@
     if ($hyper_cache_store_compressed) {
         $data['gz'] = gzencode($data['html']);
         if ($data['gz']) unset($data['html']);
+        header('Content-Encoding: gzip');
     }
     $file = fopen($hc_file, 'w');
     fwrite($file, serialize($data));
     fclose($file);

-    header('Last-Modified: ' . date("r", @filemtime($hc_file)));
+    header('Cache-Control: max-age=' . $hyper_cache_timeout);
+    header('Expires: ' . gmdate("D, d M Y H:i:s", time() + $hyper_cache_timeout) . " GMT");
+
+    // True if user ask to NOT send Last-Modified
+    if (!$hyper_cache_lastmodified) {
+        header('Last-Modified: ' . gmdate("D, d M Y H:i:s", @filemtime($hc_file)). " GMT");
+    }
+
+    return !empty($data['gz']) ? $data['gz'] : $data['html'];
 }

 function hyper_mobile_type() {

Creative Commons Lizenzvertrag Dieser Beitrag wurde unter Creative Commons Namensnennung-Nicht-kommerziell-Weitergabe unter gleichen Bedingungen 3.0 Deutschland Lizenz veröffentlicht.