Spring Sale! Save 30% on all books w/ code: PLANET24
Web Dev + WordPress + Security

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.

References

About the Author
Jeff Starr = Web Developer. Security Specialist. WordPress Buff.
BBQ Pro: The fastest firewall to protect your WordPress.

29 responses to “Compressed JavaScript Compression”

  1. Its not working in opera?

    Any solution for that?

  2. Wouldn’t it be easy to configure Apache’s mod_deflate to compress JS/CSS?

    IMHO it is much faster to serve the static file than load a PHP interpreter and process the script dynamically. Say,

    <IfModule mod_deflate.c> <IfModule mod_deflate.c> DeflateBufferSize 32768 DeflateCompressionLevel 4 <Location /> AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/x-javascript text/javascript BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4.0[678] no-gzip BrowserMatch bMSIE !no-gzip !gzip-only-text/html SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|tiff|flv|swf|zip|pdf)$ no-gzip dont-vary Header append Vary User-Agent env=!dont-vary </Location> </IfModule> </IfModule>

  3. Jeff Starr 2009/07/20 9:11 pm

    Vladimir, no argument here, however not every server is equipped with mod_gzip/mod_deflate, and many that are do not have it enabled. An example, sadly, is my current shared host at A Small Orange. They do not enable compression other than thru ob_gzhandler for HTML/PHP output.

    That method looks tight, and will try it on my shiny new Media Temple account. One note, you should only need one IfModule test for the deflate module. ;)

  4. Raina Gustafson 2009/10/13 3:39 pm

    FYI… this method worked for me on a Media Temple gridserver account, while Vladimir’s and the PP .htaccess methods above did not.

    Love the content of this site! Thanks for sharing your wisdom. :)

  5. chanfouri 2010/06/24 8:45 pm

    Thank you very much, everything works perfectly ;)

Comments are closed for this post. Something to add? Let me know.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
Banhammer: Protect your WordPress site against threats.
Thoughts
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Note to self: encrypting 500 GB of data on my iMac takes around 8 hours.
Getting back into things after a bit of a break. Currently 7° F outside. Chillz.
2024 is going to make 2020 look like a vacation. Prepare accordingly.
First snow of the year :)
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.