Sunday, April 8, 2012

Benefits of a far future expires header

A far future expires header is used for content that infrequently changes. Usually, our applications static assets (ie graphics, stylesheets and scripts) are a good fit. Most of todays sites use a JavaScript library, and together with their own code they easily have 100k of JavaScript. In addition to this, there's a few 10ks of stylesheets and probably atleast 10k of (design) graphics.

These assets only change when we modify our sites design and/or behaviour, and so it should not be necessary for our users to download these files more than once per deployment. Unfortunately, for most sites you actually download all these files on every request. By using an expires header far into the future, the browser will not download these files again before the given date. This means you can save a few hundred kb of assets on every request!
Problems with far future expires headers

The problem with the far future expires header is exactly the same as the benfit: the bowser will not download files again if the header says they haven't changed. Even if you roll out new versions that contain important bug fixes and improvements.

The way to solve this problem is to have filenames change when their contents change. Unfortunately this yields more work, and you should seek to find a way of automating this. I'll get back to this towards the end of this post.
Apache and expires headers

There's two ways of getting there with Apache. mod_expires yields the most flexible solution, but mod_headers will work too, if you cannot use mod_expires for some reason.
mod_expires

First, enable the mod_expires module. For systems using apt (Debian, Ubuntu and others) you'll do this like follows:

# Check if module is already enabled
$ ls /etc/apache2/mods-enabled | grep expires

# If it wasn't
$ sudo ln -s /etc/apache2/mods-available/expires.load /etc/apache2/mods-enabled/

# Restart Apache
$ sudo /etc/init.d/apache2 restart

Now you can use mod_expires. There are several ways to configure a future expires header (as per the documentation), I'll use ExpiresDefault inside a FilesMatch directive:

<FilesMatch "\.(ico|pdf|flv|jpe?g|png|gif|js|css|swf)$">
    ExpiresActive On
    ExpiresDefault "access plus 1 year"
</FilesMatch>

This configuration will cause all graphics, PDFs, CSS, JavaScript and flash movies to be sent out with an expires header one year from the date they were requested. This means clients always receive a date into the future, and instead use their cached copies instead.

No comments:

Post a Comment