A Simple Solution for Caching Static Files
A poorly performing website or web application leads to frustrated users and often—non-repeating visitors. There are lots of factors when you talk about web performance and I won't go into many areas, but I do want to share a simple solution for caching static files in the browser; which can yield significant improvements in load time for your website or web application.
Update: added configuration for compressing components with gzip to the sample .htaccess.
Apache is your friend and friends are good
Often described as the workhorse of the internet—Apache is a powerful web server, but often people do not know what performance gains can be obtained by adding a few simple lines in Apache’s configuration. Configuration for each site is usually controlled by the .htaccess file which resides at the root of your website or web application.
Sample .htaccess with caching options enabled
Header unset ETag
FileETag None
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ \
no-gzip dont-vary
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ \
no-gzip dont-vary
SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
<IfModule mod_expires.c>
<FilesMatch "\.(gif|png|jpg|jpeg|js|css|swf|ico)$">
ExpiresActive On
ExpiresDefault "access plus 1 years"
</FilesMatch>
</IfModule>
RewriteEngine on
RewriteRule ^(assets)/(js|css|img|swf)/(.*\.)v[0-9.]+\.(js|css|jpg|gif|png|swf)$ $1/$2/$3$4 [L]
Configuration explained
Now, let’s break down each section of the .htaccess and see what each is doing.
Disable Etag’s, they aren’t needed
Header unset ETag
FileETag None
ETag’s just increase overhead and well—we don’t want extra overhead if we are trying to reduce page load times. Enough said, let’s move on.
Compress with gzip
Compression reduces response times by reducing the size of the HTTP response. Gzip is the most popular and effective compression method currently available and generally reduces the response size by about 70%.
Add a far-futures expires header to files
<IfModule mod_expires.c>
<FilesMatch "\.(gif|png|jpg|jpeg|js|css|swf|ico)$">
ExpiresActive On
ExpiresDefault "access plus 1 years"
</FilesMatch>
</IfModule>
Expiration headers tell the browser how long to cache files. In the lines above, we are setting a far-futures expiration header of “access plus 1 years” for all images, javascript, css, swf and even ico files.
An example scenario, you have carefully crafted your CSS and you reference it in the head of your page. Presumably the CSS doesn’t change that often, so why make site visitors download it on each visit?
By setting a far-futures header of “1 year” the CSS file is downloaded on the first visit and the first visit only.
Use version numbers to “push” updated static files
Ok expiration headers are cool and all, but what if I need to make changes to my CSS file? How will I make sure the site visitor gets the new version?
Simple, when you include your files in your pages just add a version number.
<link rel="stylesheet" href="/assets/css/screen.v1.0.css" type="text/css" media="screen" charset="utf-8"/>
For most websites and applications, the process of how you update the version number can be manual. Using the example above, if I made changes to screen.css I would simply update my template to look like below:
<link rel="stylesheet" href="/assets/css/screen.v1.1.css" type="text/css" media="screen" charset="utf-8"/>
Use a rewrite rule to strip out the version number
RewriteEngine on
RewriteRule ^(assets)/(js|css|img|swf)/(.*\.)v[0-9.]+\.(js|css|jpg|gif|png|swf)$ $1/$2/$3$4 [L]
It would be a huge inconvenience to maintain multiple versions of our files (e.g. screen.v1.0.css, screen.v1.1.css). Well you don’t have to, let Apache work its magic and you only have to maintain one copy of screen.css.
The first line turns the RewriteEngine on—simple enough. The second line tells Apache to look for any requests that are in the assets folder and are in js, css, img, or swf sub-directories of the assets folder. If these two conditions are met, look for a string like “v1.1” and remove it. Leaving “screen.css”, which is what we want. Having a different version number prompts the browser to download the new file.
Putting it all together
The example we used with screen.css is only the tip of the iceberg. You probably have a javascript file for your site or app and you can use this technique for that as well. The technique is useful inside of CSS files as well, especially for background-images.
Before you try this exercise, you might want to use the YSlow plugin for Firefox and run it on your site. Take note of the grade and then implement the .htaccess file, your grade should increase significantly.*
Comments
0 so far