A Strategy for Busting Cache in WordPress

Like the other count­less users who’ve down­loaded the W3 Total Cache plugin, or manually set expires headers, I want my sites to be fast. Requests should be served from cache whenever possible. But what happens when you want to update a stylesheet in production? How can you tell your site to serve the latest version?

We’ve got a couple options on the table to accomplish this. I’ll run you through both below, with a css file as the example. Prior to the options, I’ll also provide a simple tutorial for how to setup a dynamic cache busting variable in PHP, which should update automatically for you when you make changes to your CSS file.

This tutorial will be specifically focused for Word­Press users using the wp_register_style function to call their stylesheets, but these strategies will work for busting cache on any site.

Ok, let’s get to it!

Dynamic Cache Bust­ing Variable

First, we’ll setup a variable that will update every time we make a change to our file. This variable will later go into our requests for our cacheable assets.

PHP
$cacheBusterCSS = date(“Y m d”, filemtime( get_stylesheet_directory() . ‘/library/css/style.css’));

A few things are hap­pen­ing here. First, I’m call­ing the CSS file prepended with the get_stylesheet_directory function. This function is inherent to Word­Press, and will ensure the correct absolute server path to our file, either locally or on our live site.

Next, we are wrap­ping the file call in the php filemtime function. This function returns the time when the con­tent of the file was last changed.

Finally, we’ll pass that into a date function, which will return our variable in a nice clean format, ie. 20130410. This is the value we’ll pass to our files in order to bust cache. Since it updates every time we update the file, there is no manual work.

Now, we’ll focus on actually using this variable.

Query Strings
The first option for busting cache is appending a query string to the end of our requests. We’ll use the above variable as that query string.

PHP
// cache busting variables for statics
$cacheBusterCSS = date(“Y m d”, filemtime( get_stylesheet_directory() . ‘/library/css/style.css’));

// register main stylesheet
wp_register_style( ‘main-stylesheet’, get_stylesheet_directory_uri() . ‘/library/css/style.css’, array(), $cacheBusterCSS, ‘all’ );

As you can see, I’m using the wp_register_style function to call my stylesheet in the above code. You can call yours how­ever you’d like. After setting up the source for my file, I’m then adding our cache­BusterCSS variable in as the fourth parameter, denoting a version. The version is appended to the stylesheet URL as a query string, such as ?ver=20130410. This query string will ensure the correct ver­sion of the file is sent to the client, regard­less of cache.

File Naming
The second option is renaming the file altogether when you make a change, and using a rewrite rule to reroute the requests to the original file.

.htac­cess
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] </IfModule>

This will route all requests to /path/filename.20130410.css to /path/filename.css, for example. It is scoped to the above file types, so change it as necessary.

PHP
// cache busting variables for statics
$cacheBusterCSS = date(“Y m d”, filemtime( get_stylesheet_directory() . ‘/library/css/style.css’));

// register main stylesheet
wp_register_style( ‘main-stylesheet’, get_stylesheet_directory_uri() . ‘/library/css/style.’ . $cacheBusterCSS . ‘.css’, array(), null, ‘all’ );

In our PHP, we will call the file in almost the same way as above, with a few small tweaks. Rather than passing our cache­BusterCSS variable as a query string parameter, we’ll concatenate it with the filename. Then we’ll pass null to the query string param. And there you have it! The above file will be style.20130410.css, which will route to style.css. The change in filename will bust our cache, send­ing the correct version to the client.

Which Is Better?
Well, if you’ve viewed source on my site, you can see that I’ve chosen the file renaming method. There are a few reasons for this. First, it’s the preferred method in HTML5 Boilerplate, which is about as close to a gold standard as you can get. Secondly, Steve Souders states that some popular proxies don’t cache resources with a query string.

So why include the option at all? Well, some of you may not have access to your .htaccess file for one reason or another, or may not be comfortable editing it (ignoring the obvious question of how you setup caching in the first place). It also seems to be the standard solution in WordPress, as the inherent functions support query strings.

What do you think? What strategies are you using for busting cache? I’d love to hear them!

This has been a guest post by Rob Stinogle. 

Rob is a Web Developer who appreciates the art of padding. Currently, he manages the front end team at AE.com, and writes web related jargon with his other half here. In his free time he loves climbing, painting, and re-watching Star Wars.

me