Supercharging Javascript, Part 3: Minify Everything

Previous: GZip Everything

Minification is not a new idea. I've found it tends to get used in Java and .Net apps more just because they already have a build process--something that doesn't normally occur with PHP applications. The excellent and well-regarded YUI Compressor is a Java program that is designed to be used as a command line tool, typically in a build process.

There is good reason for this attitude: good minification can be a relatively expensive operation. It's not something you'd want to necessarily do every request.

Some might question the need for minification at all if the output is already gzipped. While it is true that gzipping will do some of the job of reducing the payload size, good minification will go beyond that to renaming variables and possibly even rewriting code sections that could be shortened.

Popular libraries like jQuery and plugins often come in a pre-minified form. It's fine to use these but you'll still need to minify the scripts you write. I prefer to use the unpacked/unminified versions for debugging purposes. It's easy to change a script such as this one to minify or not depending on the environment, the user or some other setting.

My tool of choice for this job is jsmin.php, a PHP port of Douglas Crockford's JSMin, released under the MIT license.

Our script then becomes:

<?php
require 'jsmin-1.1.1.php';

// These no longer even need to be under the document root
define('SCRIPT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/script/');

$bundles = array(
  'site' => array(
    'jQuery-1.3.2.js',
    'jquery.bgiframe.js',
    'jquery.dimensions.js',
    'supersubs.js',
    'superfish.js',
    'site.js',
  ),
);

ob_start('ob_gzhandler');

$site = $_GET['site'];
if (!isset($bundles[$site])) {
  error_log("javascript.php: Unknown bundle '$site' requested");
  exit;
}
header('Content-Type: text/javascript');
$scripts = '';
foreach ($bundles[$site] as $file) {
  $contents = @file_get_contents(SCRIPT_DIR . $file);
  if ($str === false) {
    error_log("javascript.php: Error reading file '$file'");
  } else {
    $scripts .= $contents;
  }
}
echo JSMin::minify($scripts);
?>

This is, of course, concatenating and minifying on every request. We should remedy that next.

Next: Caching on the Server

2 comments:

mrclay said...

You should place "\n;" between scripts before running JSMin. This terminates a single line comment that may be open in the 1st file and makes sure two statements aren't combined from the 2 files.

Also this version of JSMin has a few more bug fixes:
http://code.google.com/p/minify/source/browse/trunk/min/lib/JSMin.php

Anonymous said...

Excelent blog entry :)

Minor typo?

I expect that

29. if ($str === false)

should read

29. if ($contents === false)

Post a Comment