Introduction to Mat Wright

Mat Wright is a Zend Certified Engineer and qualified designer available for freelance web development + consultation work.

Sunday, February 28, 2010

Apache Cache Control

The following short tutorial will show you how to set up simple Cache-Control with Apache.

It is possible to implement cache control via a .htaccess file however for optimal performance I would strongly recommend that you place the directives within your webservers httpd.conf config file.

Cache-Control rules can also be set by meta tags (http-equiv="Expires") or server-side scripting (php, asp, etc.) however the only way to really ensure that static files like javascript, css and binary files such as images and movies are cached is to configure your webserver to look after things.

This short tutorial assumes that you have the Apache module mod_expires enabled on your web server. If it is not already enabled in your Apache build you can enable this by adding the following lines to your httpd.conf file.

Apache/1.3x.

LoadModule expires_module     libexec/mod_expires.so
LoadModule headers_module     libexec/mod_headers.so

AddModule mod_expires.c
AddModule mod_headers.c
AddModule mod_gzip.c

Apache/2.0

LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
LoadModule deflate_module modules/mod_deflate.so


How To Use mod_expires
You can use the mod_expires module to set the Expires setting in HTTP headers as well as the max-age directive of the Cache-Control HTTP header in server responses.

First we set the ExpiresActive directive to 'On' to enable the generation of Expires and Cache-Control headers.

ExpiresActive On
Next, we set a default expiry time which will be used for all file types. In the example we set this to five minutes from the time that the file was accessed, therefore by default the users web browser will only use its cached copy of any file for up to five minute before downloading a fresh version from the server.

ExpiresDefault "access plus 300 seconds"
We can now create a filter to apply different cache-control conditions depending on the type of file being served. The ExpiresByType directive takes two arguments; the MIME-type and the duration for which the cached copy should be used. In the example below we direct web browsers to store html documents for 24 hours and image files for a month. You can replace the access keyword with either modified (the date the file was last modified) or now (the same as access).

ExpiresByType text/html "access plus 1 day"
ExpiresByType text/css "access plus 1 day"
ExpiresByType text/javascript "access plus 1 day"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 day"
ExpiresByType application/javascript "access plus 1 day" 
Save your httpd.conf file and reboot Apache.

Check the caching has been enabled by looking at the headers served by your server. You can check the headers in Firefox using the Live HTTP Headers plugin.

Headers, Before and After

Before the mod_expire directives were set there was no Cache-Control and the web browser downloaded a fresh copy of the file each time the user requested it.
If your web page is packed with images, javascript includes and css sheets then this could easily amount to 200Kb of data transfer per user, per page.

Date: Sun, 28 Feb 2010 10:51:57 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4 PHP/5.3.1
X-Powered-By: PHP/5.3.1
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 2483
Content-Type: text/html

200 OK 
 
With the mod_expire directives in place you can see that Apache has added the Cache-Control and Expires headers. In the example below you can see that the page was accessed on the 28 February at 10:51 and the browser will not download another copy of the document until it expires in 24 hours time on the 1st March at 10:51.

Date: Sun, 28 Feb 2010 10:51:57 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4 PHP/5.3.1
X-Powered-By: PHP/5.3.1
Cache-Control: max-age=86400
Expires: Mon, 01 Mar 2010 10:51:57 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 2483
Content-Type: text/html

200 OK 
 

2 comments:

  1. Gosh this is an old post, but one I found very useful. Could you advise why you strongly suggest that the configuration goes in http.conf rather than .htaccess files?

    ReplyDelete
  2. Simply because if you do it in .htaccess it will slow down your server response time, when if you do it in http.conf

    ReplyDelete