WP Super Cache and Browser Caching

Posted June 21, 2015 in Web Development, WordPress

I’ve been jamming on WP Super Cache these days. As great as Super Cache is (and it is great), however, you will consistently be failing in YSlow‘s “Expires Headers”, Web Page Test‘s “Cache Static Content”, and Google Page Speed Insights’ “Leverage Browser Caching”. Shouldn’t a plugin with name “Super Cache” take care of all things caching? Not necessarily.

Image of WebPage Test failing in browser caching

“Supercaching” vs. Browser Caching

Super Cache stores copies of your posts and pages in static HTML in wp-content/cache/. These are then loaded instead of querying the database and processing a PHP file every time. So, when you update a post and don’t see the changes reflected immediately, that’s because the cached, static HTML file hasn’t been updated. You then delete the cache to make sure the new content is reflected when its rebuilt. That’s “Supercaching”.

There’s another thing called browser caching that’s also pretty cool but not accounted for in WP Super Cache. Browser caching means saying, “Hey, browser, remember what this file is until I tell you to forget it”. For example, when you cache your stylesheet, the browser won’t need to load it again when you go to another page that uses the same stylesheet because it remembers it from last time.

This is where CDNs (Content Delivery Networks) can be awesome, too – if many sites use and cache jQuery from a CDN (which they do), linking your site to jQuery on that CDN means the browser likely will already have it memorized i.e. cached.

Expires Headers

You can also tell the browser how long to remember the static files. That’s what “Expire headers” refers to. For files that will not change often, like images, you want an expiration date of far in the future while files that change often can be given less far-off expiration date, or renamed when they are updated like style.css?ver=2.3.3. This is also known as cache busting. There is some debate as to whether or not the query string works, so some will actually rename the file to something like style.as4fsw2.css.

Browser Caching with .htaccess

So, how to do it? First, make a backup copy of your site root’s .htaccess file and name it something like .htaccess.bak. Then open the real one. If you are using mod_rewrite with Super Cache (which you should), you’ll have a bunch of crap in there already in addition to the rules for WordPress permalinks. Scroll down to the very end and add this:


    ExpiresActive On
    ExpiresDefault "access plus 10 days"
    ExpiresByType text/css "access plus 1 week"
    ExpiresByType text/plain "access plus 1 month"
    ExpiresByType image/svg+xml "access 1 month"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType application/x-javascript "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 week"
    ExpiresByType application/x-icon "access plus 1 year"


In plain language, this says “Browser, remember files of type [whatever] for 1 month or so”. Thanks to the CSS-Tricks Almanac for the snip. I made a slight adjustment by adding svg+xml to the mix cause we love those, too.

It is important to note, however, that you cannot add expires headers to files that are not on your server for example Typekit scripts, Google Analytics, or any scripts from embeds. So, you may still have to deal with a less than perfect score.

Also important: when you are actively updating files, you would want to set the "access plus 1 month" to "access 15 minutes" or so. And be sure to “Delete Cache” on WP Super Cache when updating the site content.

One more thing…ETags

Depending on your server, you may also see a failing grade for “Configure entity tags (ETags)” on YSlow. According to the all-knowing Wikipedia, ETags are “fingerprints” assigned to a resource that can be compared upon each request to see if the resource has changed. According to Yahoo, the actual comparison part of this process has some inconsistencies, and if you aren’t using them it’s best to remove them. Add this line right after what you put in above:

FileETag none

So…on that slightly more complicated note, happy caching! And if you are anything like me and have a problem understanding tutorials where code is introduced piece by piece, here is a gist of the .htaccess file in full.