When your building fancy AJAX websites one thing that tends to happen is you end up loading amounts of JavaScript and CSS on your pages. And while browsers are smart and do a lot of client side caching you can’t get rid of that weight on your first page load.
For example on my blog I have about 60K of JavaScript and 10K of CSS. Now this isn’t horrible but when you figure images and 90K of HTML it doesn’t take long to get to my 200K total page weight.
There are a lot of various approaches for cutting down the size of JavaScript and CSS. Some of the common ones are removing whitespace and comments for JS and CSS, or using scripts which use alternate smaller syntaxes. There are a couple problems with this approach first it just doesn’t save as much space as I’d like, you can cut 60K of JavaScript down to 30K but not 10K. Second it makes debugging horrible, every JavaScript or CSS error comes from line 1 or the file.
There is a better approach and it comes from a technology in our browsers called Content Encoding. With the right headers we can send gzip’d content to the browser and it will automatically uncompress it. All modern browsers support this so its a huge win.
So now we have figure out how to compress our content, the simplest option for static files is Apache’s mod_deflate since chances are its already installed and you can enable it with a couple minutes of poking around in your httpd conf file. But it does have the disadvantage of recompressing the files for each request so it uses up some extra cpu.
mod_gzip has a similar feature set to mod_deflate with the addition of the ability to cache the compressed files but what I really want is a solution that can run on any run of the mill apache server.
To make this happen we need to compress a JavaScript file by hand and then make Apache serve it up with the correct headers.
The headers are pretty simple, Content-Type should be text/javascript and Content-Encoding should be gzip
To set the needed headers you just need to add the following rule to apache, it can go in your httpd.conf or in a .htaccess file.
<files *.js.gz>
ForceType text/javascript
Header set Content-Encoding: gzip
</files>
You can see this in action at with a small sample I made.
Now im sure your next question is what browsers support this, from my limited testing that FireFox 1.5+ and IE 6+ both work fine. From what i’ve ready anything back to version 4 of most browsers should work.
The only only downside to this approach is you have to make sure the keep your gzipped versions of files up to date and you have to update all your code to refer to the gzipped version. I don’t have a solution to the first problem, though running gzip file.js -c > file.js.gz is handy if you want to have both the uncompressed and compressed version of the file hanging around.
I thought I had a solution for the second problem using mod_rewrite. However I haven’t been able to get it working right so if you have any tips here’s my current attempt. The conditions seem to work right, but once the rediret happens the force type and content encoding header don’t seem to get set anymore.
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_ACCEPT} >gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.+).js$ $1.js.gz [QSA,L]
</ifmodule>
Note: For testing that things are working correctly you’ll want a tool to view the headers of the http response. If you want a web based tool web-sniffer seems to work well.