How to increase site performance using cache headers for assets

An easy way to improve the performance of a website is to set cache control settings for any static assets that the website might have, such as js files, images and css.

In this article I will discuss setting up cache control in apache hosted sites. The same basic principles will still apply to other webservers, the exact syntax will vary of course.

Setting cache control in you sites vhost

This method requires both mod_expires and mod_headers to be installed and enabled in your apache installation, in most situations these will already be present and installed.

Below are some examples of setting up cache control for assets, I think it’ll be easier to explain what’s going with reference to an example rather than banging on about it. These excerpts need to be placed in your sites vhost (obvious but just thought I should mention it).

<filesMatch "\.(css|js|ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4)$">
    ExpiresActive On
    ExpiresDefault A31536000
    Header append Cache-Control "public"
 </filesMatch>

You might use this excerpt if you want to set cache settings for all of your sites assets in one fell swoop, this is generally not a good idea though and I will explain later in the article why it’s best to avoid catch all’s like this. Anywho as you can see the example uses the filesmatch directive to filter which files we are going to apply the cache settings to.

In the above instance I am selecting pretty much any asset accross the whole site, I could also specify a specific directory and a smaller set of asset types like so.

<filesMatch "/assets/\.(css|js)$">
    ....
</filesMatch>

Going back to the first examaple, ExpiresActive is required to turn on the ‘mod_expires’ module which in turn enables the use of the ExpiresDefault setting which set the expire time for the assets.

    ExpiresActive On
    ExpiresDefault A31536000

In the example I have used the ‘A’ flag which stands for last accessed, the number next to this is time measured in seconds, hence the setting in the above example above means cache this file for 29030400 seconds after first accessing it, which will mean that the assets will be cached by the users browser for roughly 1 year. Adjust this time as you see fit for your assets. If you are employing a versioning system for your sites assets then you can go ahead and set a large cache time, more about that at the end of this article.

Ok so now we move onto the header append line.

Header append Cache-Control "public"

As you may have guessed this bit of functionality comes from the mod_headers module, which allows custom headers to added in via a sites vhost. Here we are appending a ‘cache-control’ header to the response with a value of ‘public’, which just ensures that the browser will definitely try to cache the assets.

If you are using a Content Delivery Network, such as Akamai, then you may also want to set headers that instruct your particular CDN to cache these assets as well. If we wanted to do this with Akamai then we would add these lines to instruct Akamai to cache assets for a year.

Header Set Edge-Control downstream-ttl=365d
Header Append Edge-Control cache-maxage=365d
Header Append Edge-Control !no-store

So there we go, that’s the basics of setting cache control headers. I have included some further reading links at the end of this article as there are many ways of configuring cache control settings. I’m going to provide a few more examples just to cement things a bit more.

All css and javascript for roughly 6 months, including Akamai headers.

<FilesMatch "\.(css|js)$">
    ExpiresActive On
    ExpiresDefault A15768000
    Header Set Edge-Control downstream-ttl=365d
    Header Append Edge-Control cache-maxage=365d
    Header Append Edge-Control !no-store
</FilesMatch>

Turn off caching for images.

<filesMatch "\.(jpg|jpeg|png|gif)$">
    ExpiresActive On
    ExpiresDefault A0
    Header append Cache-Control "no-cache"
 </filesMatch>

Cache images for 1 week and turn off eTags.

<filesMatch "\.(jpg|jpeg|png|gif)$">
    ExpiresActive On
    ExpiresDefault A604800
    Header append Cache-Control "public"
    FileETag None
    Header unset ETag
</filesMatch>

References and further reading

Cache control is a big topic and there is much more information out there on the subject, see the pages below for some further reading.

Apache mod_expires documentation

Apache mod_headers documentation

Apache filesmatch documentation

W3C Cache-control headers definition