Caching using .htaccess
The .htaccess file is a wondrous bundle of goodness that most developers skip over.
It sits in the root directory of your website and is best known for redirecting web pages and generating 500 Internal Server Errors (when you get things wrong).
It is also used to control caching between the browser and the Apache web server.
This tutorial is targeted at XAMP server installations only. NGiNX users can use an Apache to NGiNX translator.
What is Caching?
When the browser asks the server for a file, whether it is HTML, CSS, PHP, GIF, JPEG etc, it is essentially downloading a copy of that file to the local computer or browsing device before displaying it inside the browser for your viewing pleasure.
Caching is the process of checking whether the locally stored file already downloaded can be used again or whether a new file has to be fetched from the server.
Hence caching can have a dramatic effect on the speed of your website if less files are being downloaded.
All the local computer has to do is read them from its data storage and pop them up in the browser.
You can think of it as a Blue Peter moment when they pull the completed, nicely painted super jet-pack, out from underneath the desk strewn with cut-up egg boxes, toilet roll holders, sticky-back plastic (IT’S CALLED CELLOTAPE DAMMIT!) and a handful of broken crayons.
Or when they lock the A-Team in a barn with, of course, an dumper truck, some sheets of thick corrugated iron, a dozen copper pipes and an oxy acetylene torch. Why???
And when MacGyver… Enough of the 80s reminiscing! You get the idea.
At least two modules need to be installed and turned on in your Apache server for this to work. They are bundled with the official download but not turned on by default.
The modules we’re looking for are mod_expires and mod_headers.
To find out if these are turned on you can either create a .php page with a call to phpinfo() in it or if you have SSH access you can type httpd -l to list all the modules.
Refer to the Apache documentation on how to enable these modules.
This module controls the setting of the Expires HTTP header and the max-age directive of the Cache-Control HTTP header in server responses.
Expiration dates can be set relative to the time the source file was last modified or the time when the client last accessed the source file.
Once expiration dates are set on types of files, the browser can fetch the file from its cache if the expiry date is still in the future otherwise the file will be considered expired and a new copy downloaded from the server.
Lines 1 and 16
Wrap the mod_expires specific directives in a clause to test if the module exists.
Turns the expiry rules on.
Sets the default expiry time at 5 minutes for every type of file.
The A2592000 is and old-school UNIX way of describing the number of seconds passed.
Seconds = 1 sec * 60 = 60 (secs in a minute) * 60 = 3600 (secs in an hour) * 24 = 86400 (secs in a day) * 30 = 2592000 (secs in 30 days ~a month)
Math is so cool!
Sets an expiration time of 1 day for CSS files.
So there we have some basic caching for different types of files all done within the .htaccess file in under 10 minutes.
Whereas mod_expires lets you control the max-age value for files, mod_headers gives you more control over the type of caching and when to apply it.
For example, you can duplicate the previous mod_expires example using mod_headers
Lines 1 and 13
Wrap the mod_headers specific directives in a clause to test if the module exists.
Turns on expiry rules
Lines 5 and 7
Match file types with their extensions.
Sets the max-age variable to 1 month expiry within the matched files set. Note: there is no “A” prepended here.
Sets the max_age variable to 1 day only for CSS files.
But we can do more specific cache control with mod_headers.
Turns on expiry and sets it at 3 days for all files.
Sets up caching for 1 month on a selection of media files as they’re likely not to change that much so soon.
The Cache-Control directive is set to “public” which means we’re giving permission to the browser to cache the file locally in its shared cache which may be accessible to more than just the logged in user.
Sets up a tighter cache control of 2 hours for files that are often updated like CSS or HTML files.
The Cache Control directive is set to “private, must-revalidate”.
Private tells the browser not to cache any files in shared caching folders. Files must be cached in a users private cache store.
Must-revalidate tells the browser that it should look at the max-age variable for both the locally stored file and the server and determine which one is the valid file to fetch.
Forces no caching at all on dynamic files such as PHP or script files like .pl or .cgi.
We explicitly set the expiry time to A0 (zero) and set the Cache-Control to “no-store, no-cache, must-revalidate, max-age-0”, forcing the browser never to store the file and always fetch the server copy.
As you can see, using mod_headers gives you greater control not just over the expiry time but the way that the files are stored in the cache on a local device.
There’s more information on mod_headers on the Apache website.
How to Measure Page Speed Results
As always when you are working with anything that alters the page speed of your website you are going to need tools to test the results.
We use a couple of tools to do this:
Let us know how much you managed to speed up your web pages!