Badass JavaScript

A showcase of awesome JavaScript that pushes the boundaries of what's possible on the web, by @devongovett.

UglifyJS: A Fast New JavaScript Compressor For Node.js That’s On Par With Closure

August 18th 2010

Mihai Bazon has written a new JavaScript compressor called UglifyJS that compresses code on par in size with the Google Closure Compiler, and at lightning speeds compared to YUI compressor or Closure.  The best thing about it, though, is that it is written in JavaScript on top of Node.js.

It works by parsing the inputted code using a hand-written parser ported from the parse-js Common Lisp library by Marijn Haverbeke.  Once parsed, the code is regenerated from the AST generated by the parser into compressed JavaScript.  There is also an option to pretty print the output.  Here are some of the optimizations that the compiler makes:

  • Remove whitespace
  • Shorten variable names (usually to single characters). Our mangler will analyze the code and generate proper variable names, depending on scope and usage, and is smart enough to deal with globals defined elsewhere, or with eval() calls or with{} statements.
  • Join consecutive var declarations:
    var a = 10, b = 20;  ==>  var a = 10, b = 20;
  • Remove block brackets {} where possible
  • Transform foo[“bar”] into foo.bar
  • Resolve simple constant expressions: 1 + 2 * 3 ==> 7. We only do the replacement if the result occupies less bytes; for example 1/3 would translate to 0.333333333333, so in this case we don’t replace it.
  • Various optimizations for if statements:
    • Remove “else” where possible (when the last statement in an IF block is “return”, “throw”, “break” or “continue”)
    • Transform simple ifs like:
      if (foo) bar(); else baz();  ==>  foo?bar():baz();
      if (!foo) bar(); else baz();  ==>  foo?baz():bar();
      if (foo) bar();  ==>  foo&&bar();
      if (!foo) bar();  ==>  foo||bar();

UglifyJS compresses better than YUI Compressor and just about on par with the Google Closure Compiler.  For example, the compressed version of jQuery from the Google Closure Compiler is only 403 bytes smaller than the version produced by UglifyJS - impressive!  UglifyJS is also the fastest to run by a long shot, beating Closure by over 6 seconds!

Additionally, the code produced by UglifyJS is safer than the code that Closure generates.  For example, Closure doesn’t know how to deal with eval or with{} - it just logs an error and continues to rename variables anyway.  This, obviously, leads to broken code.  UglifyJS does not have this problem:

If eval() or with{} are used in some scope, then all variables in that scope and any variables in the parent scopes will remain unmangled, and any references to such variables remain unmangled as well.

UglifyJS looks like it could be the current winner of the JavaScript compression war.  While it is a close runner up to Google Closure Compiler in compiled output size, it runs the fastest by a long run and is the safer to use than Closure.  With a little more work, it could even beat Closure in compiled size!  What do you think?  Will you use UglifyJS to compress your JavaScript?

You can check out UglifyJS out on Github, and fork away to make the compiled size even smaller.  The code looks well written and hackable.  If you want to try out the compiler without installing it yourself, you can do so here.  Great work!