Compressed JavaScript Compression
In this article, we extrapolate our favorite CSS-compression technique for JavaScript. Below, we outline the steps required to auto-compress your JavaScript documents via gzip and PHP. Two different compression methods are presented. The first method does not require htaccess, but rather involves the manual editing of JavaScript files. The second method employs htaccess to do all the work for you, thus requiring much less effort to implement. In either case, the result is the same: automatically compressed content delivered only to supportive browsers, resulting in reduced bandwidth, faster loading times, and smiling visitors :)
Method One
Overview: This method involves adding a small PHP script to your JavaScript document and replacing its .js
extension with a .php
extension.
Place the following PHP script into the top of any JavaScript document(s) that you wish to compress. Then change the .js
extension to .php
, to arrive at something similar to compressed-js.php
. Remember to use the new name when referencing the file (i.e., <script type="text/javascript" src="compressed-js.php"></script>
):
<?php
ob_start ("ob_gzhandler");
header ("content-type: text/javascript; charset: UTF-8");
header ("cache-control: must-revalidate");
$offset = 60 * 60;
$expire = "expires: " . gmdate ("D, d M Y H:i:s", time() + $offset) . " GMT";
header ($expire);
?>
Here is the same PHP script commented with functional explanations:
<?php
// initialize ob_gzhandler function to send and compress data
ob_start ("ob_gzhandler");
// send the requisite header information and character set
header ("content-type: text/javascript; charset: UTF-8");
// check cached credentials and reprocess accordingly
header ("cache-control: must-revalidate");
// set variable for duration of cached content
$offset = 60 * 60;
// set variable specifying format of expiration header
$expire = "expires: " . gmdate ("D, d M Y H:i:s", time() + $offset) . " GMT";
// send cache expiration header to the client broswer
header ($expire);
?>
Functional Summary: The previous PHP function will first check to see if the browser requesting the file will accept "gzip-deflate" encoding. If no such support is detected, the requested file is sent without compression. Next, the function sends a header for the content type and character set (in this case, "text/javascript" and "UTF-8"). Then, a "must-revalidate" "cache-control" header requires revalidation against currently specified variables. Finally, an "expires" header specifies the time duration for which the cached content should persist (one hour in this case).
Method Two
Overview: This method involves placing the PHP script in a separate .php
file and adding a set of rules to an .htaccess
file.
A more discrete, unobtrusive method for compressing JavaScript involves two steps. First, save the script provided in the first method (above) as a seperate gzip-js.php
file and place it in a JavaScript-exclusive directory. Then, add the following ruleset to an .htaccess
file located in the same JavaScript-exclusive directory (i.e., the JavaScript directory should contain only .js
files):
# JavaScript compression htaccess ruleset
AddHandler application/x-httpd-php .js
php_value auto_prepend_file gzip-js.php
php_flag zlib.output_compression On
Here is the same .htaccess
ruleset commented with functional explanations:
# JavaScript compression htaccess ruleset
# process all JavaScript files in current directory as PHP
AddHandler application/x-httpd-php .js
# prepend the PHP script to all PHP files in the current directory
php_value auto_prepend_file gzip-js.php
# compress all parsed PHP pages from current directory
# this rule is redundantly present as the first line of the PHP script
php_flag zlib.output_compression On
Functional Summary: The .htaccess
rules above first instruct Apache to parse all JavaScript files in the current directory as PHP. After this, Apache is instructed to insert the contents of the “gzip-js.php” file into the beginning of each PHP file (i.e., files with .js
extensions renamed to .php
) parsed from the current directory. And finally, Apache is instructed to compress automatically every parsed document in the current directory.
Confirmed Browsers
- Internet Explorer 5 and up: works great
- Netscape Navigator 6 and up: works fine
- Mozilla/Firefox: all versions seem to work
- Opera: does not cache compressed content
See also: Compress CSS and JavaScript with PHP at WP-Mix.
29 responses to “Compressed JavaScript Compression”
Hi Taneem, have you tried using a browser tool such as Firebug? With Firebug installed, there is a Firefox extension called YSlow that enables you to analyze many different components of your web pages, including file compression.
Regards,
Jeff
Greetings,
I had to remove the “
ob_gzhandler
” part fromob_start()
in thegzip-js.php
file, because I received this notice:Warning: ob_start(): output handler 'ob_gzhandler' conflicts with 'zlib output compression' in /blabla/gzip-js.php on line 2
When I edited that out, it works perfectly.
Yes, that error message indicates that compression is already enabled elsewhere on your server, either through Apache or via your
php.ini
file. Either way, thanks for the information — glad to hear that everything is working :)Wrap all PHP in a Try Catch block and you’ll be fine ;)
That’s what I did and works fine for me. Who knows if it was really compressed or not haha.
Thanks for this.
My pleasure, Chris — thanks for the feedback! :)
Any way to stop compressing .js via Apache? I’m getting problem with protoculuos.
I have not yet tried this, but you could theoretically disable compression in any subdirectory via HTAccess. You could also try an alternative to protoculuos, if there is such a thing.
Google have a content distribution network here
http://code.google.com/apis/ajaxlibs/documentation/#AjaxLibraries
where you can get javascript served from googles fast servers compressed, it involves adding script like
google.load("jquery", "1.2.6");
Javascript I served last month amounted to 7.67gb, looking forward to a reduced bandwidth bill.
Another excellent tip, free games! Keep ’em coming! :)
Jeff, I don’t care what my wife will say about this (I won’t show her just in case), but I absolutely love you!
For the past 48 hours, I’ve been googling for a way to compress the 46 KB mootools on my site. mod_gzip isn’t available as I have a shared account, and everything I tried didn’t work. Your first method here worked. I would have prefered the second, cleaner method, but the directory in question has a css file, not only .js. And it’s a plugin for WP, so I didn’t want to edit the plugin files, because every time I’ll update it I’ll have to repeat everything. I just edited it to change the extension to .php.
I don’t know why I didn’t find this article earlier through Google! In the future I’ll search with site:perishablepress.com in mind. :-D
Do you have some tutorial about how to compress all css and js files and deliver them in only 2 files? I have 6 css and 5 js on every page. They’re tiny files, except the mootools one, but it’s 11 requests!
Thanks!
Oh and I tried the htaccess method in js exclusive directory. But a plugin is calling for a “jquery.js?ver=1.2.6”, not just “jquery.js”. Firebug is showing me that jquery.js?ver=1.2.6 is not found… If I only knew where it’s calling from!
Any idea how to resolve this?
Thanks in advance!
@Tony: Hey, check out this method for combining and compressing CSS and JavaScript files. I haven’t tried it yet, but it looks very promising!
For the second question, search your files for the “
jquery.js?ver=1.2.6
” character string to determine the source of the call..