Closure Compiler vs Rollup vs Webpack
syntaxsuccess.com
syntaxsuccess.com
https://github.com/roman01la/webpack-closure-compiler
https://github.com/camelaissani/rollup-plugin-closure-compil...
I think it works better for GWT than for Closure because GWT's optimizer permits inlining functions in some circumstances even if they increase code size. This causes repetitious fragments to appear, and re-ordering the code to bring those fragments within GZIP's compression window functions as kind of a late-stage "anti-inliner/common subexpression elimination"
Is there a specific reason why simple code elimination is not as wide spread as tree shaking, although it seems to be simpler and more effective solution?
The Javascript version of the Closure-Compiler is
transpiled by GWT from the Java source. For more details
on the differences in behavior see the super sourced
files in the main repo.It's been a while since I've used closure. I may look into this to do a comparison on my current open source project and see what difference, if any, it makes.
Case in point: We just installed the latest version on a new computer yesterday, and it causes some JS code that runs fine in its original form to fail on IE11 after transformation. The original code isn't complicated at all and multiple developers and lint tools think it's correct and not doing anything non-standard, but the transformed version seems to confuse IE. In fairness to Closure Compiler, we also can't immediately see why the transformation it has applied would be invalid, so maybe this is really a bug in IE's JS parser or something along those lines. Unfortunately, the fact remains that the original code works, the slightly different transformed version from a previous version of Closure Compiler also worked, but the transformed code in the new version does not.
function unusedFunction(note) {
alert(note['text']);
}
function displayNoteTitle(note) {
alert(note['title']);
}
var flowerNote = {};
flowerNote['title'] = "Flowers";
displayNoteTitle(flowerNote);
to: var a={};a.title="Flowers";alert(a.title);
For comparison, rollup created: function displayNoteTitle(note) {
alert(note['title']);
}
var flowerNote = {};
flowerNote['title'] = "Flowers";
displayNoteTitle(flowerNote);
... (which you'd then have to minify, but as you can see it only eliminated the unused function).[1] https://developers.google.com/closure/compiler/docs/api-tuto...
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?
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.ISTM if we're going to compress the file anyway, renaming would have a much smaller effect on what actually gets served?
https://github.com/psychonautwiki/mw-UserBadge/blob/master/u...
After applying Google Closure Compiler in advanced mode:
https://github.com/psychonautwiki/mw-UserBadge/blob/master/u...
(There isn't even a prototype chain like it babel)
Beautified version of compiled version:
https://gist.github.com/anonymous/1b6b96ec319f1272f9bbc3f19b...
I think that gives the whole thing a very new kind of aesthetics
alert("Flowers");
Can't get any better than that.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
Malte Ubl has exposed some of this functionality to the outside world with his Splittable project (https://medium.com/@cramforce/introducing-splittable-1c882ba...)
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