"reorder_funs" - sort function declarations by complexity
This reduces the size after gzip. Complexity is (for now) measured simply by counting AST nodes.
This commit is contained in:
parent
9676167aac
commit
f8dd879873
|
|
@ -326,6 +326,10 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
||||||
|
|
||||||
- `hoist_funs` -- hoist function declarations
|
- `hoist_funs` -- hoist function declarations
|
||||||
|
|
||||||
|
- `reorder_funs` -- rearrange function declarations in order of increasing
|
||||||
|
complexity. This has no effect on size before gzip, but often reduces size
|
||||||
|
after gzip.
|
||||||
|
|
||||||
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
||||||
by default because it seems to increase the size of the output in general)
|
by default because it seems to increase the size of the output in general)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ function Compressor(options, false_by_default) {
|
||||||
loops : !false_by_default,
|
loops : !false_by_default,
|
||||||
unused : !false_by_default,
|
unused : !false_by_default,
|
||||||
hoist_funs : !false_by_default,
|
hoist_funs : !false_by_default,
|
||||||
|
reorder_funs : !false_by_default,
|
||||||
keep_fargs : true,
|
keep_fargs : true,
|
||||||
keep_fnames : false,
|
keep_fnames : false,
|
||||||
hoist_vars : false,
|
hoist_vars : false,
|
||||||
|
|
@ -108,14 +109,12 @@ merge(Compressor.prototype, {
|
||||||
},
|
},
|
||||||
before: function(node, descend, in_list) {
|
before: function(node, descend, in_list) {
|
||||||
if (node._squeezed) return node;
|
if (node._squeezed) return node;
|
||||||
var was_scope = false;
|
var was_scope = node instanceof AST_Scope;
|
||||||
if (node instanceof AST_Scope) {
|
|
||||||
node = node.hoist_declarations(this);
|
|
||||||
was_scope = true;
|
|
||||||
}
|
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
node = node.optimize(this);
|
node = node.optimize(this);
|
||||||
if (was_scope && node instanceof AST_Scope) {
|
if (was_scope && node instanceof AST_Scope) {
|
||||||
|
node = node.ast_complexity(this);
|
||||||
|
node = node.hoist_declarations(this);
|
||||||
node.drop_unused(this);
|
node.drop_unused(this);
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
}
|
}
|
||||||
|
|
@ -152,10 +151,26 @@ merge(Compressor.prototype, {
|
||||||
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
||||||
node._squeezed = false;
|
node._squeezed = false;
|
||||||
node._optimized = false;
|
node._optimized = false;
|
||||||
|
node._complexity = 0;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AST_Node.DEFMETHOD("ast_complexity", function(){
|
||||||
|
var self = this;
|
||||||
|
var complexity = 0;
|
||||||
|
self.walk(new TreeWalker(function(node){
|
||||||
|
if (node._complexity) {
|
||||||
|
complexity += node._complexity;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
complexity++;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
self._complexity = complexity;
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
function make_node(ctor, orig, props) {
|
function make_node(ctor, orig, props) {
|
||||||
if (!props) props = {};
|
if (!props) props = {};
|
||||||
if (orig) {
|
if (orig) {
|
||||||
|
|
@ -1574,6 +1589,14 @@ merge(Compressor.prototype, {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
self = self.transform(tt);
|
self = self.transform(tt);
|
||||||
|
if (compressor.option('reorder_funs')) {
|
||||||
|
// Moving simpler functions earlier tends to give better gzip compression
|
||||||
|
hoisted.sort(function (a, b) {
|
||||||
|
var aComplexity = a._complexity;
|
||||||
|
var bComplexity = b._complexity;
|
||||||
|
return (aComplexity - bComplexity) || (a.start.pos - b.start.pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (vars_found > 0) {
|
if (vars_found > 0) {
|
||||||
// collect only vars which don't show up in self's arguments list
|
// collect only vars which don't show up in self's arguments list
|
||||||
var defs = [];
|
var defs = [];
|
||||||
|
|
|
||||||
33
test/compress/reorder-funs.js
Normal file
33
test/compress/reorder-funs.js
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
reorder_functions_after_optimize: {
|
||||||
|
options = {
|
||||||
|
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||||
|
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||||
|
reorder_funs:true, keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function longFun(x, y) {
|
||||||
|
return [x, y].map(function (x) {
|
||||||
|
return x*x;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function medFun(x) {
|
||||||
|
return 15*x;
|
||||||
|
}
|
||||||
|
function shortFun() {
|
||||||
|
return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function shortFun() {
|
||||||
|
return 55;
|
||||||
|
}
|
||||||
|
function medFun(x) {
|
||||||
|
return 15*x;
|
||||||
|
}
|
||||||
|
function longFun(x, y) {
|
||||||
|
return [x, y].map(function (x) {
|
||||||
|
return x*x;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user