Wordpress's WP-Super-Cache's Super Cache with nginx
(Apologies for the triple-layer title, but it's a specific subject involving a badly named plugin.)
This has been explained before (the progenitor for most other examples on the net seems to be this forum post), but the solution was ugly and slightly incomplete. nginx's lack of a one-line RewriteCond equivalent means there will never be an elegant solution, but I think I've come up with something clearer.
First, background. WP Super Cache has two levels of caching:
- "WP Cache". Whenever Wordpress's index.php renders a page, a copy of the page output is stored in
/blog/wp-content/cache(and themetasubfolder). For future requests for the same page, this cached copy is served byindex.php. The good: subsequent requests don't hit the database or re-run your badly coded widgets for every visitor. The bad: PHP still runs for every request. - "Super Cache". As well as a copy of page output being stored as per above, a copy is also stored in
/blog/wp-content/supercache, in a structure that mirrors your blog's URL hierarchy. With clever use of rewrite rules at your webserver layer, you can entirely skip loading PHP & Wordpress for any request that a cached file has been created for.
The WP Cache layer always works. The rest of this post is about making use of the Super Cached files with your shiny nginx server. For reference, the Apache rules are here. This nginx code follows the same order and structure, but has some differences. Read:
location /blog {
gzip_static on;
Aside: gzip_static requires an nginx configured with --with-http_gzip_static_module. If your build isn't, and you don't want to compile your own, just remove this directive. Instead of serving pre-compressed Super Cache files to clients that support compression, nginx will compress them on the fly (like normal).
set $supercache "";
if ($request_method = GET) {
set $supercache "${supercache}G";
}
if ($args = "") {
set $supercache "${supercache}A";
}
if ($http_cookie !~ (comment_author_|wordpress_logged_in|wp-postpass_)) {
set $supercache "${supercache}C";
}
if (-f $document_root/blog/wp-content/cache/supercache/$http_host$request_uri/index.html) {
set $supercache "${supercache}F";
}
# If we met all the conditions, serve the supercached file
if ($supercache = GACF) {
rewrite ^ /blog/wp-content/cache/supercache/$http_host$request_uri/index.html break;
}
# Otherwise pass to wordpress as normal
if (!-e $request_filename) {
rewrite ^ /blog/index.php last;
}
}
# The cache files should not be directly accessible to clients
location /blog/wp-content/cache { internal; }
# Configure the PHP backend as per normal
location ~ (\.php$) {
include fastcgi_params;
if (-e $request_filename) {
fastcgi_pass unix:/tmp/nginx-php-fastcgi.sock;
}
}
Done! If you have problems, three pointers:
- WP Super Cache has a very big settings page. You can set them as you like mostly, but make sure you set this and this (if you're using gzip_static).
- Check the bottom of the source of your pages to see if a page was server from the cache, and if so, whether it was served from the Super Cache.
- If you need to troubleshoot, make liberal use of the logging facility that WP Super Cache implements.
Leave a Reply