Should you switch to UglifyJS2?

Every now and then somebody asks me if UglifyJS v2 is ready for production use. I'd say
it is, but it's hard to back that claim without a lot of users. Version 1 got some huge popularity boost after John Resig's twit about it and after jQuery switched to it. Thanks to being so popular, a lot of issues were
identified and fixed. Something similar needs to happen to V2.

Here are some views on the status of V2 compared to V1 and other compressors.

Numbers

UglifyJS2 is slightly slower than version 1, but compression overall is better. It's still a lot faster than Google
Closure (with one exception1) and provides similar savings — depending on the test case, UglifyJS2 might be slightly better (especially after
Gzip) or slightly worse than Closure. I also included Esmangle in my stats, but it's far behind. I did not include
YUI Compressor because it's no longer relevant (seems YUI switched to UglifyJS v1 to provide JavaScript
compression).

Note: some of the libraries below use the global eval function. UglifyJS will normally prevent
any name mangling from taking place in this case, resulting in bigger output. Since Closure doesn't do that (it just
mangles names regardless of whether eval or with are in use), I enabled name compression in
UglifyJS2 too, for a fairer comparison.

How stable?

Other than my own code, which is pretty big and seems to work correctly after minification with V2, I run the test
suites of a few libraries on compressed code:

The last one is developed by Telerik. Telerik is my new employer, and as I
recently joined the Kendo UI team, first thing I did was modifying its test suite to work with code compressed by
UglifyJS2. I caught and fixed a couple of issues with the compressor, and now the impressive 12K+ tests all pass
successfully.

So there you go: if you ask me, it is production-ready.

What's better than V1

First off, the code in version 2 is a lot bigger than V1. This isn't good news, but it happened for good reason.
It's more modular and it doesn't use arrays, but objects instead, to represent AST nodes.
The advantage is the ability to store location information and comments in the AST. Thanks to this, V2 is able to
generate source maps2 or to retain certain comments in the output—features that were long requested but were extremely tricky to add on
top of the first version.

Compression is more aggressive than in V1. V2 is able to discard mutually referencing functions if they are
otherwise unused (which V1 didn't); it also discards unused variables or function arguments. It can detect a wider
range of potential problems with the input files, such as “condition always true/false” etc. Also, it will work harder
than V1 to reduce the number of statements, leading to potential removal of unnecessary brackets.

For these reasons it's a bit slower than V1, but not by much. Compression is a bit better, but again—not by
much—and that's because the most significant savings are
due to renaming local variables and discarding whitespace. Everything else is fighting for mere bytes.

Should you switch to V2?

If you only care about minification and don't care about generating a source map or keeping comments in the output,
then V1 will probably continue to work fine for you. Note, however, that I don't plan to add any more features to
V1.

If you care about slightly better compression, generating a source map, or using a software that's new and
maintained, then you should switch. If you want to help making UglifyJS2 the best JS compressor, then you should
switch. If you're afraid that it might not be production-ready, then by all means, switch now! You should
find that I'm very responsive—if you find any show-stopper problems please file an issue at Github and expect a quick answer from my side
(well I can't promise, of course, but generally I will try to address any serious issue in less than one day).

Big Thanks to Telerik!

In closing, here's a big Thank You to Telerik for offering me a job. Telerik is also one of the bakers of my
successful funding campaign for UglifyJS2 and they have expressed willingness to allow me to maintain UglifyJS as part
of my job, which is great for the whole community!

Uglifying “processing.js” with V2 takes 10 seconds! That's embarrassingly slow and I'll look into the particular
optimization that causes the slowness as soon as I have some time. It's the “unused” flag—this optimization discards
unreferenced functions and variables. Pass -c unused=false to disable it, and it's a lot faster (takes
about 2 seconds instead of 10).

I can report v2 won't build Twitter Bootstrap 2.2.2 (Responsive) as of 14 Dec 2012. I had to downgrade to v1 per Cuong Tran's answer at bit.ly/Uucef5
I use a single, global nodejs setup (everything via npm with -g flag).
Bootstrap is getting extremely popular so you should test with it regularly if you don't already.
Thank you for the wonderful software and I must say, it is a delight to see a website built with Lisp.

Kindly post advice on retaining v1 during a system-wide upgrade;
npm update -g
I spent hours looking, but found nothing obvious or simple. Update as shown installs v2 and so breaks Twitter Bootstrap. It took time to isolate this problem and I find no fix except upgrading by hand, one package at a time. Of course I'm no expert in nodejs or npm but a system built around the notion of dependency graphs should make this task trivial.

Packages that depend on the old version of UglifyJS should be explicit about the version they expect, i.e. should contain the following in package.json:
... "dependencies": {
"uglify-js": "~1"
}
"~1" means >= 1.0.0 and < 2.0.0.
I'm not sure how to install multiple versions globally, but there is probably some NPM trick for this.

Thank your for the answer, appreciated. I will footnote as follows.
1. The issue posed wasn't multiple global versions of UglifyJS. It was holding v1 fixed during mass global upgrade. There is no v2 installed.
2. No package dependency exists. Twitter Bootstrap isn't a nodejs package.
3. Let us know when UglifyJS can build it!

Well, seems to me that Twitter is using a simple Makefile which uses the UglifyJS command line tool. It is designed for v1. Check this file:
https://github.com/twitter/bootstrap/blob/master/Makefile#L30
Search for lines containing "@uglifyjs", for example:
@uglifyjs docs/assets/js/bootstrap.js -nc > docs/assets/js/bootstrap.min.tmp.js
The fix is simple, v2's CLI is incompatible and expects different arguments, for example to compress and mangle:
@uglifyjs docs/assets/js/bootstrap.js -cm > docs/assets/js/bootstrap.min.tmp.js
That should do it. Please check the README for more information about the supported arguments.