If you’re looking for some quick ways to improve the performance of your site, Steve Souder’s High Performance Web Sites is packed with great advice. You don’t even need to buy the book as most of the information is available through links from the Firefox YSlow plugin. We have been picking one rule every couple of weeks to focus on and this past week we spent a bit of time adding far future expires headers for the Flex SWFs on our site.

Far future expires means setting the expires HTTP header for static content to some date far in the future. Effectively, this means that static content within a web site will always be loaded from the browser cache after it is first requested. This has the impact of greatly improving the load time for your site as well as reducing the number of requests sent to your web servers. The flip-side, however, is that because the cached content never expires, if you do need to change an image or a stylesheet then the user will need to clear their browser cache before they see it.

Hence, taking advantage of far future expires means taking responsibility for versioning static content on the server. Any time static content changes, it needs to be served up from a different URL. In his book, Steve Souders alludes to the approach that they follow at Yahoo! to achieve this, but he doesn’t give enough detail to just go ahead and implement it. So here is how we’re solving the problem.

We’re currently using two approaches to versioning static content: one for images and one for SWFs, CSS, and Javascript:

  • Every time an image is added to our site, we place it in a folder named after the current release (ie. /images/1.21/header.png). If we need to update an image then we move it from the folder it’s in to the folder for the current release and then update all links to the image accordingly. While this approach does require some manual effort, it has the advantage of being incredibly simple and easy to get going immediately. Because images change relatively infrequently within the site, this approach creates minimal overhead. It also only means that images that have changed from release to release get reloaded. The majority of the images will stay cached because they haven’t changed.
  • Other static content like stylesheets, scripts and Flex applications change more frequently. They are versioned automatically with every build by getting copied to a folder named after the current build number and then bundled into the deployment package. We then dynamically build the path/URL to these resources using the current build number loaded from a bundled text file resource. This approach has the benefit of being completely automated. The only (small) disadvantage is that the version of the content changes with every release (as we’re releasing every week, this is quite often) regardless of whether the content has changed or not. However, given that this content generally changes weekly, it isn’t a problem.

As far as setting the expires and cache control headers, we’re using nginx as a reverse proxy server which makes it trivial to set HTTP headers by the file extension for each requested URI.

If you have suggestions for a better way to version static content or if I can provide more clarity on the approach that we’re using, please let me know.