Reputation: 1886
I'm trying to minify node.js style modules for Espruino (a microcontroller that runs JavaScript). These modules often have hidden internal constants and convenience functions defined, and I want to collapse those down.
As a very contrived example, let's say I have:
var C = {
CONST1 : 32,
CONST2 : 64
};
function Foo() {
}
Foo.prototype.C = {
ONE : 1,
TWO : 2
};
function doStuff(x) {
return x+1;
}
Foo.prototype.getConst = function (x) {
return doStuff((x==this.C.ONE) ? C.CONST1 : C.CONST2);
}
exports.foo = function() { return new Foo(); };
I'd like to minify this down to:
function Foo(){}Foo.prototype.C={ONE:1,TWO:2};Foo.prototype.getConst=function(a){return a==this.C.ONE?33:65};exports.foo=function(){return new Foo};
However currently I'm using the closure compiler online service and this will either do a simple minification in 'Simple' mode (not folding in the hidden C
and doStuff
):
var C={CONST1:32,CONST2:64};function Foo(){}Foo.prototype.C={ONE:1,TWO:2};function doStuff(a){return a+1}Foo.prototype.getConst=function(a){return doStuff(a==this.C.ONE?C.CONST1:C.CONST2)};exports.foo=function(){return new Foo};
or on 'Advanced' it'll go mad, rename the functions and remove everything:
function a(){}exports.a=function(){return new a};
So how do I tell it to keep all children of exports
and everything referenced by those children intact (with the same names)?
Wrapping the code in:
(function(){
...
})();
Has the desired effect, but then I have to strip out (function(){
and })();
from what is returned, which seems like a bit of a cludge.
Or is there another minifier (it doesn't have to be online) that would handle this correctly?
Upvotes: 0
Views: 195
Reputation: 1886
Well, it looks like the only solution was to do as I'd originally mentioned in the question, regardless of how much of a cludge it was:
Wrap the code in:
(function(){
...
})();
Pass it to the closure compiler with SIMPLE_OPTIMIZATIONS, and then strip out (function(){
and })();
from the beginning and end of the response.
This allows the closure compiler to do constant folding, to completely remove the C
array in a lot of cases, and to really reduce the code size.
So with the example above, instead of:
var C={CONST1:32,CONST2:64};function Foo(){}Foo.prototype.C={ONE:1,TWO:2};function doStuff(a){return a+1}Foo.prototype.getConst=function(a){return doStuff(a==this.C.ONE?C.CONST1:C.CONST2)};exports.foo=function(){return new Foo};
I get:
function a(){}a.prototype.C={ONE:1,TWO:2};a.prototype.getConst=function(a){return(a==this.C.ONE?32:64)+1};exports.foo=function(){return new a}}
Which is a pretty significant saving in not only code size, but also the memory needed to execute that code.
Upvotes: 0
Reputation: 12275
You can minify local names with uglifyjs -m toplevel
.
As for folding, I believe it's usually not possible in javascript. In your particular case it'll work, but general code is usually too complex for static analyzer to do tricks like that.
Upvotes: 1