Compressing files on Apache with mod_deflate

Posted in Apache -

It's possible with the Apache web server to compress files that are sent to the browser so less bandwidth is consumed and the load time should generally be faster. The module in Apache 2.0 and up is called mod_deflate and for older versions of Apache there was, what I recall as being, a third party module called mod_gzip. In this article I am looking at mod deflate on Apache 2.x

In order to compress files using mod_deflate on Apache 2.x you first need to load the module, so you'll need to edit the Apache configuration. The exact location of the configuration file varies between each Linux/BSD distro, but it's often found at /etc/httpd/httpd.conf or /etc/apache2/httpd.conf, or /etc/httpd/conf/httpd.conf or /etc/apache2/conf/httpd.conf. If you are unsure of its location locate httpd.conf will usually send you in the right direction.

So now that you've found the Apache config file, open it up in your favourite text editor as root or using sudo, and add this line:

LoadModule deflate_module modules/

and this section:

<Location />
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/x-js text/css

The above example will compress all html, plain text, xml, javascript and css files. You can change which are compressed by adding to or removing from the list above when you add it to your configuration. You can also vary it on a virtualhost by virtualhost basis, and/or a directory by directory basis. The above example, added to the main httpd.conf file will apply it to all virtualhosts on the web server.

After you've adjusted the httpd.conf settings you'll then need to reload Apache:

/etc/init.d/httpd reload

The affect of mod_deflate can be seen in a couple of examples below, with compression enabled for javascript and css. The following are extracts from the Apache log file before and after mod_deflate was enabled. The file size is bolded.

No compresssion: - - [02/Nov/2007:10:09:19 +1300] "GET /js/prototype.js HTTP/1.1" 200 122911 "-" "Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.7 (like Gecko) SUSE" - - [02/Nov/2007:10:17:02 +1300] "GET /style/style.css HTTP/1.0" 200 7039 "-" "Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.7 (like Gecko) SUSE"

Compression enabled - - [02/Nov/2007:10:12:32 +1300] "GET /js/prototype.js HTTP/1.1" 200 28138 "-" "Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.7 (like Gecko) SUSE" - - [02/Nov/2007:10:16:10 +1300] "GET /style/style.css HTTP/1.1" 200 2149 "-" "Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.7 (like Gecko) SUSE"

As you can see, the Javascript file was 122911 bytes when not compressed and 28138 bytes when compressed; the CSS file was 7039 bytes when not compressed and 2149 bytes when compressed. Results will vary depending on the contents of the file.

Some file types are already compressed, such as graphics files, music files and similar, so you shouldn't attempt to compress those files types. Generally it will just be text files that you would want to compress.

On a final note, compressions takes up additional CPU cycles and memory at both the server and the client, so you need to be careful about what you compress. For example it may be much better to leave HTML, CSS or Javascript files served in their normal state if they are quite small anyway because the overhead required to compress and decompress may not justify the small amount of bandwidth savings.

The full documentation for mod_deflate can be found in the Apache documentation

A note on the mime types

25 June 2008... I was setting this up for another site for Javascript files and discovered the files were not being compressed. After messing around for a little while I realised that Apache was using a different mime type for Javascript and as soon as I changed it and reloaded again it worked.

On Apache on CentOS 5.x the mime types are located from /etc/mime.types but this location will vary from distribution to distribution. If you locate the "TypesConfig" directive in your Apache httpd.conf this will show you where it's getting them from, and you can ensure you are using the correct mime type.

Alternatively, use Lynx or similar to do a headers dump on the file and it will tell you want the mime type is, e.g.:

$ lynx -head -dump
HTTP/1.1 200 OK
Date: Wed, 25 Jun 2008 03:25:53 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Wed, 25 Jun 2008 03:24:47 GMT
ETag: "38016-d9de-37f45dc0"
Accept-Ranges: bytes
Content-Length: 55774
Connection: close
Content-Type: application/x-javascript

The Content-Type: line tells us the mime type is "application/x-javascript" so it's then just a matter of putting this into your location directive like so (obviously putting your appropriate mime type(s) there):

<Location />
    AddOutputFilterByType DEFLATE application/x-javascript

and then reload Apache again.

Related posts: