Using Apache mod_expires to control browser caching

Posted in Apache -

Apache's mod_expires module allows settings by file type to control how long browsers cache files. This is useful for ensuring browsers cache image, Javascript and/or CSS files without making additional unecessary requests when loading pages.

Making sure mod_expires is enabled

mod_expires may not be enabled by default in your Apache install. On a Debian based system (e.g. Debian, Ubuntu and their derivitives) run the following command to enable mod_expires:

sudo a2enmod expires

The resulting output will look like this:

Enabling module expires.
Run '/etc/init.d/apache2 restart' to activate new configuration!

Follow the instructions to restart Apache to enable mod_expires. If it had already been enabled you would instead see this:

Module expires already enabled

On a RHEL/CentOS based system, edit /etc/httpd/conf/httpd.conf and make sure the following line is not commented out, restarting Apache after making any changes.

LoadModule expires_module modules/

Configuring mod_expires

Add any required rules to the .htaccess file in the website's root directory. If there isn't already an .htaccess file then create one.

The file should contain this line:

ExpiresActive on

And then the necessary rules. To configure how long a file type should be cached for, add a line following this rule:

ExpiresByType [mime type here] "access plus [number] [timeframe]"

The timeframe should be one of years, months, weeks, days, hours, minutes or seconds.

Here's an example from one of my sites:

ExpiresActive on
ExpiresByType application/javascript "access plus 1 months"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 months"

This ensures that all Javascript, image and CSS files on the website are cached for a month from the first request. Because the browser will cache these quite aggressively, if any changes are made to the files they will not be reflected in the browser. If changes to a file are required then the filename must be changed to avoid caching issues, so be sure to set rules carefully.

(Please note that the mime type for Javascript can vary somewhat depending on the distro and version of Apache used. Read my "Content-type for Javascript with Apache" post for some more details about this).

I personally have a system in place for websites where I use these rules so that whenever changes are made to the Javascript or CSS files they are given unique names - see my "Force reload of updated CSS and Javascript files with unique filenames" for an example of how this can be accomplished without having to rename the files each time.

As far as images are concerned, I create new files with unique names if they need to be changed.

By doing this with the expires rules I am able to get the browsers to do a high level of caching but still have them get fresh files if and when I need them to.

Related posts: