Intuitively I would assume that for most codebases dead-code removal would have the biggest impact, especially when importing third-party libraries and only using portions of them.
But from your comment I can see that rollup should be able to handle this too. Yet the data in the linked article seems to imply Google Closure compiler still can optimize the code 33% further.
I find it hard to imagine that inlining functions can make that kind of difference.
Is it the test which contains flawed data? Or is this just an area where it's hard to generalize results due to the varying characteristics of different code-bases? Anyone got an opinion?
I compared the output bundles (ran them back through a beautifier for sanity) and it looks like a lot of the benefit comes from the aggressive renaming.
Compare this section of the rollup output:
return e || (e = new zh({
enableLongStackTrace: dt()
})), e.run(function() {
var r = yh.resolveAndCreate([{
provide: zh,
useValue: e
}], n.injector),
o = t.create(r),
l = o.injector.get(th, null);
if (!l) throw new Error("No ErrorHandler. Is platform module (BrowserModule) included?");
return o.onDestroy(function() {
return _t(n._modules, o)
}), e.onError.subscribe({
next: function(t) {
l.handleError(t)
}
}), bt(l, function() {
return o.injector.get(bh).donePromise.then(function() {
return n._moduleDoBootstrap(o), o
})
})
})
To this from Closure compiler:
var c;
c || (c = new Af({
Lm: yh()
}));
return c.run(function() {
var d = Ne([{
sb: Af,
Be: c
}], a.s),
e = b.create(d),
f = e.s.get(ee, null);
if (!f) throw Error("No ErrorHandler. Is platform module (BrowserModule) included?");
e.ec(function() {
return Hh(a.mi, e)
});
c.hq.subscribe({
next: function(a) {
f.handleError(a)
}
});
return Ch(f, function() {
return e.s.get(Ze).xp.then(function() {
Eh(a, e);
return e
})
})
})
On top of that I did a basic comparison of the number of times the 'function' keyword is present in each bundle:
$ ag --count function eg-closure.js
eg-closure.js:2905
$ ag --count function eg-rollup.js
eg-rollup.js:4421
Whether this is from inlining or 'better' dead-code removal I can't really tell.
There are too many optimizations in Closure Compiler to describe simply what it does. It is a full blown optimizing compiler like C, right down to supporting graph coloring in the naming of locals. It even does type-based optimization by disambiguating property names on prototypes by types (https://github.com/google/closure-compiler/wiki/Type-Based-P...) -- this alone I've measured at 14% code size reduction in my projects, and it can move code at the function level out of the main module into late loaded modules if it detects the code is not used until later.
All of Google's main projects, from the Google Home page, to Docs, Gmail, Maps, etc rely on Closure Compiler. Google Photos makes particularly aggressive use of this splitting functionality (take a look at the network tab in Chrome)
Closure Compiler also pairs well with Google Style Sheets, which is a style sheet compiler like SASS/LESS (but predated them), but it optimizes and prunes CSS.
Closure has it's downsides, the Advanced Mode makes assumptions about the way you write Javascript that can break. However, there are conformance checks you can enable to check for many of these. The compiler has to "see" what you're doing, so if you do something like this:
foo.hello = 42;
function blah() { return "hello"; }
foo[blah()] = 42;
The compiler may not be able to see that 'foo.hello' and 'foo["hello"]' are the same thing, and the former will get renamed to foo.xyz. The price you pay huge savings in code size is being consistent and diligent in your code, and sometimes giving up a little bit of dynamism
Closure compiler understands how the code runs, whereas those other tools only understand how its parsed.
Closure compiler is really awesome but never fully caught on outside of Google because it doesn't let you use some features of JS that aren't optimizable. The main one I can remember is only allowing dot syntax for properties
[1] https://developers.google.com/closure/compiler/docs/api-tuto...