Uglify/Uglify2, Rickshaw, Requirejs and Minification
By Adrian Sutton
If you have:
- A javascript project using require.js
- Which is optimised using r.js
- Includes Rickshaw or any other library that uses the prototype class system
Then you are very likely here because you’re trying to enable JavaScript optimization (minification) and finding that suddenly stuff breaks.
The problem is that the prototype class system allows overriding methods to call the original method by adding a $super as the first parameter to the function. From the prototype docs:
When you override a method in a subclass, but still want to be able to call the original method, you will need a reference to it. You can obtain that reference by defining those methods with an extra argument in the front:
$super
. Prototype will detect this and make the overridden method available to you through that argument. But to the outside world, thePirate#say
method still expects a single argument. Keep this in mind.
The problem is, the first parameter has to be called $super but enabling optimization causes it to be renamed to something shorter, thus breaking prototype’s class system.
The solution, which is easy to find on the internet is to exclude the $super parameter from renaming. What’s not as obvious to find is the exact way to do that since it depends on which optimization engine you’re using.
For uglify, you’re build.js should look a bit like:
({ ... optimize: 'uglify', uglify: { except: ["$super"] }, ... })
For uglify2, you’ll want:
({ ... optimize: 'uglify2', uglify2: { mangle: { except: ["$super"] } }, ... })
I’d highly recommend using uglify2 and then also enabling source maps with:
({ ... generateSourceMaps: true, preserveLicenseComments: false, optimize: 'uglify2', uglify2: { mangle: { except: ["$super"] } } ... })
The key part of getting configuration working for the optimizer is to get the magical nesting level right – lots of places point you towards the “except” config you need, but most put it in the wrong place so it has no effect.