I'm working on a snappy new web application which imports several javascript and css files which could benefit from gzip compression to the browser. Compression, of course, will help improve bandwidth usage and load times.
The first thing to know is you can't assume a client browser will accept gzipped content. We need to check the request headers for something like this:
Accept-Encoding: gzip,deflate
Each of the options below does this in some way or another.
One option is to use mod_deflate. This causes CPU overhead, and is not supported by many shared webhosts because of it. So we can't distribute an application assuming we can use mod_deflate. Deflate compresses files as they are requested.
To use mod_deflate, you'd add something like this to your config or htaccess:
<IfModule mod_deflate.c>
AddOutputFilter DEFLATE js css
</IfModule>
A second option is to use MutliViews in mod_negotiation. MultiViews allows Apache to choose a file based on the browser's request headers and is designed to specifically support different encoding and languages which a client browser claims to support. This method allows to you pre-compress your files and avoid the overhead associated with on-the-fly compression.
To use mod_negotiation to handle gzip, you'd add something like this to config or htaccess:
Options +MultiViews
AddEncoding x-gzip .gz
You'd create two versions of each file:
myscript.js.en
myscript.js.gz
Then, in your application, you'd link to non-existent file:
<script type="text/javascript" src="/img/spacer.gif">
But, as you can tell, if MultiViews isn't enabled for some reason, the application will request the file "myscript.js" and since the file doesn't exist (and cannot exist, or else MultiViews won't try and find the correct file), we get a 404 and the application breaks. If you're distributing your application across multiple server types and configurations, your application will just plain break. This also won't work if a browser doesn't support the English language (should be very rare).
The third and most appealing option is to use mod_rewrite and combine the best of the first two methods, pre-compression and conditional file responses.
To use mod_rewrite to handle gzip, you'd add something like this to config or htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule (.*\.(js|css))$ $1.gz [L]
</IfModule>
AddEncoding x-gzip .gz
<FilesMatch .*\.css.gz>
ForceType text/css
</FilesMatch>
<FilesMatch .*\.js.gz>
ForceType application/x-javascript
</FilesMatch>
The mod_rewrite configuration checks the client headers for gzip support then checks to see that the .gz version of the file exists before rewriting the request for the .gz version. AddEncoding ensures the gzip content encoding header is sent to the browser. The ForceType directives make sure the proper content type is sent to the browser for the .gz extensions.
Then you'd create two versions of each file (you don't have to do this for all files, just the most compressible):
myscript.js
myscript.js.gz
Then, in your application, you'd link to file:
<script type="text/javascript" src="/img/spacer.gif">
Now your application is both fast and portable.
Additionally, if you wanted to make sure compression was available even if you hadn't supplied a pre-compressed version of the file, add the mod_deflate support from the first method:
<IfModule mod_deflate.c>
AddOutputFilter DEFLATE js css
</IfModule>