This commit is contained in:
Geraint 2017-03-11 03:01:50 +00:00 committed by GitHub
commit e62c72a199
3 changed files with 65 additions and 5 deletions

View File

@ -381,6 +381,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)

View File

@ -65,6 +65,7 @@ function Compressor(options, false_by_default) {
toplevel : !!(options && options["top_retain"]), toplevel : !!(options && options["top_retain"]),
top_retain : null, top_retain : null,
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,
@ -146,14 +147,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);
} }
@ -238,6 +237,7 @@ 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;
} }
if (reduce_vars) { if (reduce_vars) {
if (node instanceof AST_Toplevel) node.globals.each(reset_def); if (node instanceof AST_Toplevel) node.globals.each(reset_def);
@ -375,6 +375,21 @@ merge(Compressor.prototype, {
} }
}); });
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) {
@ -2004,6 +2019,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 = [];

View 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;
});
}
}
}