Should you switch to UglifyJS2?

  • Published: 2012-11-08
  • Modified: 2012-11-08 10:17
  • By: Mishoo
  • Tags: uglifyjs, javascript, minification
  • Comments: 5 (add)
Nov
8
2012

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).

The following table shows some results. Open them as a chart.

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!

Footnotes
1.

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).

2.

It's this single feature what prompted me to start a completely new version.

5 comments. This is HOT!

Add your comment

# Mark
2012-12-15 07:38
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.
# Mark
2012-12-21 02:57
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.
# Mishoo
2012-12-21 11:24
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.
# Mark
2012-12-29 05:53
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!
# Mishoo
2012-12-29 10:28
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.