How can it determine dead code for such a dynamic language like JavaScript?
Is it limited to obvious stuff like things after a "return;" statement that cannot run? Because I don't see how it could remove unused functions when you can invoke them in such indirect ways: myobj['f'+'oo']();
You have to restrict your code to a certain style (and there are warnings for whenever you're defeating the DCE, I believe). You'll particularly see this when you're accessing properties via array-index-like lookup (your myObj['f'+'oo']) example) instead of e.g. myObj.foo under advanced compilation, where the property name will have been munged and doesn't exist.
Like anything else, there are tradeoffs, and Closure asks that you restrict yourself to a more predictable set of patterns in return for the benefits it offers.
You tell the compiler a file that it's not allowed to dead-strip. From there, it then computes the transitive closure of the rest of your code that is referenced from the "entry point", and removes everything else. It is, of course, possible to reference things in indirect ways that the compiler can't see, so they provide some mechanisms to force inclusion if necessary.
You have to follow a set of rules - your example would not be allowed.
One of the nice things about ClojureScript is that the compiler will output compatible code, so you don't even really have to think about it (except when doing JS interop). If you write valid ClojureScript, it Just Works.
Basically when enabled it will rewrite normal property access, e.g: `myObj.foo` to something like `a.b` but wont shorten string literal access, e.g `myObj['foo']` just becomes `a.foo` which you would use for any API's you want to export.
For a real-world example I use string literals for declaring jquip's public API:
Thanks - I remember seeing that when looking through the docs, but I don't really like that either, unfortunately. I'm using Uglify right now, and I was thinking of adding a pre-minify step that walks the AST for a JSDoc-style annotation on either the properties themselves or a containing object, and pulls out the list of property names to preserve that way.
The title of this submission omits the best part; closure provides static type checking. That is more valuable to me than the dead code removal & minification.
I just discovered an amazing and nearly undocumented feature of the Closure Compiler: the --module flag.
That means if you have 10 pages, you have 10 compile passes, even if 95% of your code is shared. But, it turns out you can run a compile pass and output multiple compiled .js files simultaneously! This has cut my build times by 10x.
So, anyone with long build times due to multiple separate builds, poke around and find out how to use --module!
The Google Summer of Code project is unrelated to code splitting which is what --modules is referring to in this context. The ClojureScript GSoC project was about integrating the variety of JS module formats (CommonJS, AMD, ES2015) found in the wild as well as supporting preprocessing phases (React's JSX).
I think it's likely that long-term, the approach FB took with Flow (or more general Abstract Interpretation methods) should be able to handle more cases with less effort on the developer's side (albeit with increased computational costs).
The modules/"code motion" is a bit strange at first glance, but definitely a huge boon for building debuggers/admin interfaces/etc. that you don't want included in your main application. David Nolen wrote about this earlier this year when support started landing in ClojureScript http://swannodette.github.io/2015/04/07/in-stillness-movemen...
Edit: wrt Flow, specifically referring to FB's approach to retrofitting type-checking into a largely dynamic language. Thanks to swannodette for pointing out the ambiguity.
It's not clear what you're referring to wrt. "the approach FB took with Flow" and Abstract Interpretation. Type checking? Dead code elimination? In anycase, Google Closure Compiler also leverages Abstract Interpretation.
Closure would probably be the most interesting (or close to the most interesting) project to work on inside of Google-proper, for me personally. That said, Google's approach is very much on the opposite side of FB's, in that Google expects the vast majority of code to be written for it. FB is dealing with a legacy codebase and has fewer engineers, so has to strike a different set of tradeoffs - less up-front work to integrate their tooling for potentially less benefit than something like Closure can deliver. It's interesting to see the two different approaches.
Anyway, this thread is about Closure, which enables ClojureScript, which is my go to language these days. The developers working on the compiler and the stdlib (which is amazing) should feel proud about all the people they've enabled.
> The title of this submission omits the best part
We reverted the submitted title ("Closure Compiler parses JavaScript, removes dead code, minimizes what's left"). Submitters: please don't use the titles of HN stories to editorialize. If you want to say what you think is important about an article, please do so in the thread, where all commenters are equal.
I keep trying to use closure on my projects but it doesn't compile jQuery to working code. I always get errors after concatenating and using it on my sources and this always just brings me back to uglify.
Google Closure is not only a useful tool at the command line, it's also an incredibly powerful framework for manipulating, analyzing, checking, and producing JavaScript in a dizzying number of ways. And now thanks to Java 8's Nashorn you can skip the Java and script it quite productively with JS, https://gist.github.com/swannodette/aad077de18309a08cff3
Why is the closure library not as popular as other alternatives (ex: jquery)? It looks like a solid library, used by gmail, google docs and other google apps, I'm guessing is the java requirement for the compiler.
You can't write regular code to take advantage of its advanced features- It requires you to program in a strict subset of regular javascript, and that is a bit of a PITA.
The Java requirement is a real pain. If someone made an npm package that took care of the Java requirements, we'd probably all be using Closure rather than something like Uglify. Closure usually does slightly better minification wise, but it's a pain to work with.
Huh? I mean I'm a little confused. The js ecosystem is full of transpilers, build tools, frameworks, and a bunch of package managers but installing java is one too many?
Well all those build tools are usually npm packages, and are easily managed as dependencies using package.json (hence why there are so many being used). Adding Java and and a secondary set of dependencies isn't really worth the 5% decrease in minified file size that closure might give you.
I did try to use closure instead of uglify in a project recently - closure was a real pain to deal with compared to tools with equivalent functionality that are written in JavaScript. Cross-language ecosystem tools rarely work well it seems.
It shouldn't matter - but it does. Native dependencies are pretty important so a lot of effort has gone into solving that issue - but I don't think making Java and Node.js work together well is a high priority for anyone.
That said, closure being in JavaScript has more to do with choosing rhino than anything else. If you were starting a project like closure today you wouldn't use Java.
Re: advanced mode, totally depends on what kind of code you've got. Lots of inlineable functions and constants? Double digits easily. Lots of objects and DOM? 5% better than uglify is optimistic.
Actually if it was started at Google today, it probably would use Java or Go. Very few development tools are written in JS at Google. Angular and Polymer (and maybe Traceur) build tools being the exception. Our internal tooling works far better with statically typed languages.
It should be rather trivial to have a gulp/grunt task that installs Java and runs CC. CC could even be packaged as a EXE if desired.
It works fine because node take care of compiling it and lot of packages in npm need it so you are practically forced to install a C / C++ compiler, but java here is almost alone, so the requirement is more painfull.
Because really taking advantage of it (enabling advanced compilation options) requires using a fairly specific subset of the language otherwise it will DCE half the project. Integration with "regular" javascript libraries can also be annoying.
ClojureScript uses Closure as an optimisation backend, since the primary cljs compiler is already in java.
FYI - I'm fairly certain that CLJS does not use Google Closure because it is "already in java", but rather because of it's maturity and awesome features like DCE.
This and that are not exclusive. There are good reasons to use closure, but would integrating closure and the tooling it requires even have been considered had the cljs compiler been in anything but java?
How many alt.js languages implemented in !java use closure?
When playing with this library, I had the same thought because it provides such powerful static analysis. JSDoc generation is nice. There's even externs for common libraries like Node.js core [1].
I stopped working with it (for now at least), because I couldn't figure out how to get my Node.js library to compile correctly. So at least for me the learning curve was a barrier to use it.
Beats the pants of it - if you can live with the limitations.
It doesn't change string access, but it does rewrite dot access so you have to use dot access except when dealing with e.g json.
It doesn't work with the with statement, or code that is run with eval. You have to specifically export functions that should be used outside the code, otherwise they may be inlined, renamed or deleted.
Finally to get the most out of it, you have to write jsdocs for its types (at which point it can now do things like inlining functions).
Different beasts. A direct comparison is unfair to either of them.
Uglify does minification and dead code removal. That's really it.
Closure does a lot of type checking, code rewriting, and has a very specific subset of JS that you'll have to use if you really want to get the best performance out of it... and does minification and dead code removal.
If you just want minification/dead code removal then Uglify is waaay faster, javascript native, and almost as small (105-120% of the size of Closure compressed code, depending on the code). It also doesn't use the JVM so that can make dep management/ops simpler if you don't already have java in your stack. YMMV.
If the advanced stuff sounds like something you'd want/need (if you have a large project and don't mind writing to the Closure optimizations) then Closure is certainly worth looking at. It's very good at what it does.
I've been using Closure Compiler with ADVANCED_OPTIMIZATIONS (which does the dead-code removal) for soundslice.com for several years. It is truly awesome!
The downside is that, in order for the dead-code elimination to work properly, you need to make sure to "export" things that aren't explicitly called in your JS module. For example, if your JavaScript module just provides some functions that are called by a web page, you'll need to make sure those function calls are "seen" by the compiler so that it doesn't delete them. It just takes a bit of time and thinking to set this up; I believe it originally took me a day to do so for Soundslice.
Having used both this an Uglify... I can't recommend this.
It's slow. Like... really slow to build. Uglify takes ~10seconds on my code whereas CC took around 10 minutes. Plus the performance benefits - while real - provides very little useful speedup that the V8/whoever JIT won't do anyhow. Even in tight loops.
It's VERY cool, but will add minutes to your deploy/compile time for very little practical benefit. If you're doing a ton of data processing on the client (WHY??) then I guess it might be useful... maybe.
That said - I'm glad it exists. It's a technological benefit even if it's not practically that useful. Those who compare it to the C++ optimization flags are being hyperbolic however: C++ isn't a JIT compiled language so it's Apples to Oranges.
10 minutes? I'm sorry this is just FUD. I've seen very large ClojureScript projects that generate nearly 100,000 lines of JavaScript and even with advanced optimization (the slowest mode by far) I've never seen it take longer than a minute and a half.
As far as Uglify compression performance, in my experience it consistently generates a final production file twice as large as Closure if you're following the Closure conventions. And Uglify doesn't do the fancier things like code splitting + code motion.
Not FUD - you just clearly don't have a large enough project. I'm dealing with a lot more JS than you. Like.. a LOT more. I wish I had only 100k lines.
As for twice as large - never seen that. Uglify routinely gets to between 10-20% larger than advanced optimized CC in my experience.
I mean if you're writing directly for CC you might get better but that's because a lot of that will directly make it harder for most other minifiers (go figure)
Like I said tho CC is great, I'm glad it exists. It CERTAINLY does more than Uglify... I just don't see any practical benefit.
100k lines? You think that's a large project? The closure library itself has 500kloc.
10-20% is a huge difference. On an 1M JS app, that would be an extra 100-200k of JS downloaded. That will seriously increase latency, especially for those in developing countries.
There is definitely something amiss with your setup if you had a Closure compile take ten minutes. That is absolutely not the norm. On an old laptop processing thousands of lines of JS, I've never had it take more than a minute.
I work on Gmail/Inbox and not even our codebase takes 10 minutes. Closure Compiler does not need to be constantly run in optimized mode during development. Type-checking only mode is faster, and engineers at Google typically develop code in uncompiled mode, and let the continuous integrations server run the fully optimized build + integration tests.
Secondly, this isn't about strictly speeding up runtime performance, but startup latency. The biggest use of Javascript compilers is shrinking download size. The effects of even a 10% code size reduction are readily apparent in 95%tile latency graphs. On mobile web, it's even more of a benefit.
Third, on a large codebase, like Gmail, Docs, Maps, etc the type checking provided by Closure is invaluable.
Forth, Closure provided a good module system for JS for far longer than any alternative, and like GWT, it's over 10 years old. That module system allows for cross-module code motion optimizations, that make it easy to structure your code for maximum readability and productivity, but to ship it down the wire in a way that only the code that is needed immediately is retained, and "dead code" is moved into late loaded modules.
Have a look at https://photos.google.com/ Most of the files loaded are tiny. Why? They're globally optimized, uglified, and dead-stripped together, but code is moved around between fragments depending on when, not if, the code is needed.
Soap Box Time: The way your message goes over the top reminds me of a frequent irritation I have with part of the JS community, I guess I'd call it the "tools derangement syndrome". People who chafe at any structure imposed, be it optional types, syntactic-sugar Classes in ES6, IDEs, build processes, dismissing the benefits, or overplaying the downsides.
That's fine if you don't have a lot of code, but if you have a big enough project that Closure would take a long time to optimize, you are exactly the kind of scale of project that needs a type checking globally optimizing compiler.
Closure compiler is extremely practically useful. Without it, Gmail, Maps, Docs, et al would be far larger applications that consume more resources. It's simply the best Javascript optimizer on the market by far.
Hi there, love the work you guys do. For perspective: I used to be the Closure cheerleader in our company. You don't have to sell me on it, I know it has very good features.
> not even our codebase takes 10 minutes
It's probably better than ours. Not going to argue that. I think if our codebase wasn't a giant legacy beast it would perform better. It doesn't though :(
> engineers at Google typically develop code in uncompiled mode
Well we did that too, but when we had to bundle everything and compile.. it sucked. We managed to get it down to about ~3 minutes with less advanced options but at that point Uglify was on par with it size-wise so... shrugs
We took development time over a minor (basically insignificant) startup latency improvement.
> on a large codebase [..] the type checking provided by Closure is invaluable.
I don't disagree with this but I find it best to separate the two out (for example, with something like Flow, etc) rather than have the whole bundle/compile step fail. But it's a good feature.
> Closure provided a good module system for JS for far longer than any alternative
True, but if you're using ES6 you get a better one now so I can't really say this is a plus anymore. If anything it's bloat now.
> The way your message goes over the top reminds me of a frequent irritation I have with part of the JS community, I guess I'd call it the "tools derangement syndrome". People who chafe at any structure imposed, be it optional types, syntactic-sugar Classes in ES6, IDEs, build processes, dismissing the benefits, or overplaying the downsides.
That's not what I'm doing. I'm saying in my experience and on our codebase it's not been worth using. I'm sure it will be for many people but I can't recommended right now. That's a personal perspective sure; never claimed it wasn't.
Ironically I'd say you're doing the exact thing you're arguing against - getting massively riled up over criticism of your favorite tool chain.
> That's fine if you don't have a lot of code,
Yeah, I do. A lot. Like... a lot. Like... over 3,600,000 LOC. It's just it's clearly not the kind of code and/or project that CC is fast at optimizing right now. That's on the project: it's very legacy and bloated tbh. I'm working to fix that as we speak ;)
> Closure compiler is extremely practically useful.
For projects that it's useful for, yes. It's a tautology. However for my project: wasn't at all. For projects that really just want minification and obfuscation: it's also total overkill.
I'm not saying its bad, GOD NO! Not at all, just that it was - for the large codebase we have - really not the best choice. That may change as our project gets cleaner, better organized, and less legacy. Right now though we're not there.
I'm not attacking that CC exists, I was providing an alternative perspective from the love-fest in here: where I've found it lacking. Blind devotion isn't good for any project. It's a good project but it doesn't help everyone.
If you just want minification/obfuscation (not dead code stripping), sure, CC is overkill. But if you've got a 3.6M LOC shipping to consumers and not a B2B/intranet app, I can't believe you wouldn't care about an extra 10-20% dead code stripping, that's a non-trivial improvement.
Also, have you tried it recently? AFAIK, there was performance work done on it over the past year or so, speeding up the type checker and other parts of the compiler.
My view is generally, it's better to spend time at compile time. Even if a fully optimized build took 10 minutes, it's not a big deal. Even in an uncompiled mode, presumably your integration tests on a large app can take minutes to run anyway, and with such a large app, you may have a Q/A process as well. That is, your releases will be gated by other factors, not compile times, and so a few extra minutes to save 100k downloads * number of users is a big benefit for your user base and a few minutes of your time.
I would say that if you have any deferred loading, CC's cross module code motion is a fear that all of the other existing tools lack and it can get you far far more than 10% reduction of your initial load depending on how your app is written. Generally the larger the app, the more likely transitive dead code will be pulled into the initial download without something like CC.
> I can't believe you wouldn't care about an extra 10-20% dead code stripping, that's a non-trivial improvement.
Care? Sure, we do, but honestly we can probably get that by being smarter with our code atm. Like I said - it's pretty legacy in many (most) areas.
And to be fair - it was much closer to the 10% figure most of the time than the 20. Sometimes less.
Given our kind of unoptimized dev flow (for JS anyhow, we're pretty good overall) it meant that Closure was just... more of a pain in the ass (for many reasons, the JVM didn't help either, yet another moving part).
So we chose dev productivity over it. When our codebase is more streamlined and modern-looking I think we'll re-evaluate and trust me Closure will be on that list.
> have you tried it recently?
About 6 months ago. Was better, just not as smooth a flow and fast as Uglify was. Glad to hear that it's an ongoing effort though.
> My view is generally, it's better to spend time at compile time.
Generally I'd agree... if it wasn't that our dev flow often had to include compiles (due to... reasons I can't get into here). This is a problem we're working to fix on our end but it did make Closure a lot more annoying, unfortunately. We did used to use it, so I'm not talking from a position of not having used it here :)
> Generally the larger the app, the more likely transitive dead code will be pulled into the initial download without something like CC.
Generally agree. However we have a LOT of strange orphan code (that we're clearing up) which means our dead-code was surprisingly low across the project while perhaps still dead code at some specific point of access.
Annoying? Yes. Edge case? Perhaps. I think it's more common in large old projects than any developer would like unfortunately.
Thankfully there is roadmap and we WILL be evaluating Closure when we get further along. Like I said - I used to be the main cheerleader for it here.
Since we're reasoning about a concrete case (abrinthebay's codebase): Wouldn't the amount of code-stripping benefit be directly proportional to how much unused code the codebase has?
It's possible in abrinthebay's scenario, they simply haven't crammed in so many Javascript libraries that the code-stripping can find 10-20% unused code.
(I'm also having a hard time avoiding calling "the code stripper yanks 10-20% of my code" an indicator that one's choice of libraries is wastefully large, but that's a separate thread of debate).
It's unavoidable in a large project unless your build dependencies are down to the method level. Typically library targets don't supply a single method, they supply a file which has a number of methods, and not all of them are used.
But even in the case where you don't get dead stripping, you'll still get deferred code motion. And even if you don't get deferred code motion, you'll still get better renaming, because with type analysis, you can know which properties are disjoint from others.
At some point the argument gets into the "I don't need a C compiler, because I already write fast, efficient ASM code" territory. If your code base is perfectly gardened, ok, you don't need any compiler tools. The statistically likelihood of that situation remaining stable as your project ages and adds more developers approaches zero IMHO.
Read it more closely; the document I linked is specifically about pushing functionality into the client.
"MVC frameworks, such as AngularJS, have been developed that enable client-side developers to build powerful and compelling UIs."
"This paper provides best practices and guidance to web developers who are interested in AngularJS or other client-side MVC technologies and want to optimize their server backend for these technologies."
"The growing popularity of client-side MVC frameworks such as Backbone.js and AngularJS is representative of this shift to the client. These frameworks help reduce complexity and increase reuse in even the simplest of applications... As the UI moves to the client, the server becomes simpler."
Yes, I'm quite aware of what Angular, Backbone, etc do. I'm also quite aware of what MVC is thankyouverymuch.
But I was specifically referring to data processing on the client and while those frameworks obviously can do that the page you linked describes where they farm it out to other cloud services.
This is obviously faster than doing it on the client.. and is exactly what I was talking about.
The future you linked to is the exact opposite of doing data processing on the client. So why you'd call client-side data processing the future with that link as evidence I don't know.
... unless you don't actually understand what "client side" means I guess. Client Initiated Processing !== Clint Side Processing.
I'm very curious how you're coming up with your Uglify performance claims on this thread for a near 4MLOC JS codebase. I just tried Uglify on 6mb of ClojureScript generated JavaScript (it's nowhere near 4MLOC) and it takes nearly ~34 seconds on 3.5ghz iMac. That's 3 times slower then your 10 second claim for your own code base which sounds orders of magnitude larger!
3-4X slower than Uglify I could believe, but saying Closure is 60X slower and claiming compression performance I cannot even reproduce with a code base that's 40-50X smaller. What???
I've never seen more than a minute on our codebase for Uglify. It could also be we were doing something stupid with Closure and slowing it down (like stopping then spinning up the JVM for each package for example) which is certainly possible.
However if we add in some of the more computationally heavy Uglify options it will go up somewhat.
But, for what it's worth, without a "seamless JS interop" - and without Haxe being JS.
For me these are of no concern and I'd probably use Haxe had I the right project for it, but for most JS-and-only-JS people it's a deal breaker. I will never be friends with one of those programmers.
I have used the Closure Compiler for years (and contributed too!).
It is really a fantastic tool (along with the Closure Library and other members of the Closure family) for anyone that values maintainable, solid JS.
I can understand why it's not more popular; it feels a lot like Java -- industrial strength, non-flashy, and perhaps a little boring. It's also a little hard to setup for a real project (tutorials could be better).
It has been around since the creation of Gmail, and will be around to stay for years to come. (Though it has improved substantially over the years.)
76 comments
[ 3.9 ms ] story [ 140 ms ] threadIs it limited to obvious stuff like things after a "return;" statement that cannot run? Because I don't see how it could remove unused functions when you can invoke them in such indirect ways: myobj['f'+'oo']();
Like anything else, there are tradeoffs, and Closure asks that you restrict yourself to a more predictable set of patterns in return for the benefits it offers.
One of the nice things about ClojureScript is that the compiler will output compatible code, so you don't even really have to think about it (except when doing JS interop). If you write valid ClojureScript, it Just Works.
Basically when enabled it will rewrite normal property access, e.g: `myObj.foo` to something like `a.b` but wont shorten string literal access, e.g `myObj['foo']` just becomes `a.foo` which you would use for any API's you want to export.
For a real-world example I use string literals for declaring jquip's public API:
Which closure advanced rewrites to: Original: https://github.com/mythz/jquip/blob/master/dist/jquip.all.jsCompiled: https://github.com/mythz/jquip/blob/master/dist/jquip.all.cl...
https://developers.google.com/closure/compiler/docs/api-tuto...
I just discovered an amazing and nearly undocumented feature of the Closure Compiler: the --module flag.
One of the most inconvenient parts of using closure is having to compile each page separately. That's what the Closure docs say to do: https://developers.google.com/closure/compiler/docs/api-tuto...
That means if you have 10 pages, you have 10 compile passes, even if 95% of your code is shared. But, it turns out you can run a compile pass and output multiple compiled .js files simultaneously! This has cut my build times by 10x.
So, anyone with long build times due to multiple separate builds, poke around and find out how to use --module!
https://github.com/clojure/clojurescript/wiki/Google-Summer-...
The modules/"code motion" is a bit strange at first glance, but definitely a huge boon for building debuggers/admin interfaces/etc. that you don't want included in your main application. David Nolen wrote about this earlier this year when support started landing in ClojureScript http://swannodette.github.io/2015/04/07/in-stillness-movemen...
Edit: wrt Flow, specifically referring to FB's approach to retrofitting type-checking into a largely dynamic language. Thanks to swannodette for pointing out the ambiguity.
Closure would probably be the most interesting (or close to the most interesting) project to work on inside of Google-proper, for me personally. That said, Google's approach is very much on the opposite side of FB's, in that Google expects the vast majority of code to be written for it. FB is dealing with a legacy codebase and has fewer engineers, so has to strike a different set of tradeoffs - less up-front work to integrate their tooling for potentially less benefit than something like Closure can deliver. It's interesting to see the two different approaches.
Anyway, this thread is about Closure, which enables ClojureScript, which is my go to language these days. The developers working on the compiler and the stdlib (which is amazing) should feel proud about all the people they've enabled.
We reverted the submitted title ("Closure Compiler parses JavaScript, removes dead code, minimizes what's left"). Submitters: please don't use the titles of HN stories to editorialize. If you want to say what you think is important about an article, please do so in the thread, where all commenters are equal.
I'm using Visual Studio for the backend, in case it matters.
I did try to use closure instead of uglify in a project recently - closure was a real pain to deal with compared to tools with equivalent functionality that are written in JavaScript. Cross-language ecosystem tools rarely work well it seems.
Closure advanced mode will do a lot better than 5% compared with Uglify.
That said, closure being in JavaScript has more to do with choosing rhino than anything else. If you were starting a project like closure today you wouldn't use Java.
Re: advanced mode, totally depends on what kind of code you've got. Lots of inlineable functions and constants? Double digits easily. Lots of objects and DOM? 5% better than uglify is optimistic.
It should be rather trivial to have a gulp/grunt task that installs Java and runs CC. CC could even be packaged as a EXE if desired.
ClojureScript uses Closure as an optimisation backend, since the primary cljs compiler is already in java.
https://github.com/clojure/clojurescript/wiki/Rationale#goog...
How many alt.js languages implemented in !java use closure?
I stopped working with it (for now at least), because I couldn't figure out how to get my Node.js library to compile correctly. So at least for me the learning curve was a barrier to use it.
[1] https://github.com/dcodeIO/node.js-closure-compiler-externs
It doesn't change string access, but it does rewrite dot access so you have to use dot access except when dealing with e.g json.
It doesn't work with the with statement, or code that is run with eval. You have to specifically export functions that should be used outside the code, otherwise they may be inlined, renamed or deleted.
Finally to get the most out of it, you have to write jsdocs for its types (at which point it can now do things like inlining functions).
Uglify does minification and dead code removal. That's really it.
Closure does a lot of type checking, code rewriting, and has a very specific subset of JS that you'll have to use if you really want to get the best performance out of it... and does minification and dead code removal.
If you just want minification/dead code removal then Uglify is waaay faster, javascript native, and almost as small (105-120% of the size of Closure compressed code, depending on the code). It also doesn't use the JVM so that can make dep management/ops simpler if you don't already have java in your stack. YMMV.
If the advanced stuff sounds like something you'd want/need (if you have a large project and don't mind writing to the Closure optimizations) then Closure is certainly worth looking at. It's very good at what it does.
Choose the right tool for the job and all that.
Check out 39:30 in my 37signals talk at http://37signals.com/talks/soundslice to find out more about it.
The downside is that, in order for the dead-code elimination to work properly, you need to make sure to "export" things that aren't explicitly called in your JS module. For example, if your JavaScript module just provides some functions that are called by a web page, you'll need to make sure those function calls are "seen" by the compiler so that it doesn't delete them. It just takes a bit of time and thinking to set this up; I believe it originally took me a day to do so for Soundslice.
It's slow. Like... really slow to build. Uglify takes ~10seconds on my code whereas CC took around 10 minutes. Plus the performance benefits - while real - provides very little useful speedup that the V8/whoever JIT won't do anyhow. Even in tight loops.
It's VERY cool, but will add minutes to your deploy/compile time for very little practical benefit. If you're doing a ton of data processing on the client (WHY??) then I guess it might be useful... maybe.
That said - I'm glad it exists. It's a technological benefit even if it's not practically that useful. Those who compare it to the C++ optimization flags are being hyperbolic however: C++ isn't a JIT compiled language so it's Apples to Oranges.
As far as Uglify compression performance, in my experience it consistently generates a final production file twice as large as Closure if you're following the Closure conventions. And Uglify doesn't do the fancier things like code splitting + code motion.
As for twice as large - never seen that. Uglify routinely gets to between 10-20% larger than advanced optimized CC in my experience.
I mean if you're writing directly for CC you might get better but that's because a lot of that will directly make it harder for most other minifiers (go figure)
Like I said tho CC is great, I'm glad it exists. It CERTAINLY does more than Uglify... I just don't see any practical benefit.
It's an awesome technological achievement though.
10-20% is a huge difference. On an 1M JS app, that would be an extra 100-200k of JS downloaded. That will seriously increase latency, especially for those in developing countries.
I have 3.6 million to deal with. Different scale entirely.
Secondly, this isn't about strictly speeding up runtime performance, but startup latency. The biggest use of Javascript compilers is shrinking download size. The effects of even a 10% code size reduction are readily apparent in 95%tile latency graphs. On mobile web, it's even more of a benefit.
Third, on a large codebase, like Gmail, Docs, Maps, etc the type checking provided by Closure is invaluable.
Forth, Closure provided a good module system for JS for far longer than any alternative, and like GWT, it's over 10 years old. That module system allows for cross-module code motion optimizations, that make it easy to structure your code for maximum readability and productivity, but to ship it down the wire in a way that only the code that is needed immediately is retained, and "dead code" is moved into late loaded modules.
Have a look at https://photos.google.com/ Most of the files loaded are tiny. Why? They're globally optimized, uglified, and dead-stripped together, but code is moved around between fragments depending on when, not if, the code is needed.
Soap Box Time: The way your message goes over the top reminds me of a frequent irritation I have with part of the JS community, I guess I'd call it the "tools derangement syndrome". People who chafe at any structure imposed, be it optional types, syntactic-sugar Classes in ES6, IDEs, build processes, dismissing the benefits, or overplaying the downsides.
That's fine if you don't have a lot of code, but if you have a big enough project that Closure would take a long time to optimize, you are exactly the kind of scale of project that needs a type checking globally optimizing compiler.
Closure compiler is extremely practically useful. Without it, Gmail, Maps, Docs, et al would be far larger applications that consume more resources. It's simply the best Javascript optimizer on the market by far.
Hi there, love the work you guys do. For perspective: I used to be the Closure cheerleader in our company. You don't have to sell me on it, I know it has very good features.
> not even our codebase takes 10 minutes
It's probably better than ours. Not going to argue that. I think if our codebase wasn't a giant legacy beast it would perform better. It doesn't though :(
> engineers at Google typically develop code in uncompiled mode
Well we did that too, but when we had to bundle everything and compile.. it sucked. We managed to get it down to about ~3 minutes with less advanced options but at that point Uglify was on par with it size-wise so... shrugs
We took development time over a minor (basically insignificant) startup latency improvement.
> on a large codebase [..] the type checking provided by Closure is invaluable.
I don't disagree with this but I find it best to separate the two out (for example, with something like Flow, etc) rather than have the whole bundle/compile step fail. But it's a good feature.
> Closure provided a good module system for JS for far longer than any alternative
True, but if you're using ES6 you get a better one now so I can't really say this is a plus anymore. If anything it's bloat now.
> The way your message goes over the top reminds me of a frequent irritation I have with part of the JS community, I guess I'd call it the "tools derangement syndrome". People who chafe at any structure imposed, be it optional types, syntactic-sugar Classes in ES6, IDEs, build processes, dismissing the benefits, or overplaying the downsides.
That's not what I'm doing. I'm saying in my experience and on our codebase it's not been worth using. I'm sure it will be for many people but I can't recommended right now. That's a personal perspective sure; never claimed it wasn't.
Ironically I'd say you're doing the exact thing you're arguing against - getting massively riled up over criticism of your favorite tool chain.
> That's fine if you don't have a lot of code,
Yeah, I do. A lot. Like... a lot. Like... over 3,600,000 LOC. It's just it's clearly not the kind of code and/or project that CC is fast at optimizing right now. That's on the project: it's very legacy and bloated tbh. I'm working to fix that as we speak ;)
> Closure compiler is extremely practically useful.
For projects that it's useful for, yes. It's a tautology. However for my project: wasn't at all. For projects that really just want minification and obfuscation: it's also total overkill.
I'm not saying its bad, GOD NO! Not at all, just that it was - for the large codebase we have - really not the best choice. That may change as our project gets cleaner, better organized, and less legacy. Right now though we're not there.
I'm not attacking that CC exists, I was providing an alternative perspective from the love-fest in here: where I've found it lacking. Blind devotion isn't good for any project. It's a good project but it doesn't help everyone.
Also, have you tried it recently? AFAIK, there was performance work done on it over the past year or so, speeding up the type checker and other parts of the compiler.
My view is generally, it's better to spend time at compile time. Even if a fully optimized build took 10 minutes, it's not a big deal. Even in an uncompiled mode, presumably your integration tests on a large app can take minutes to run anyway, and with such a large app, you may have a Q/A process as well. That is, your releases will be gated by other factors, not compile times, and so a few extra minutes to save 100k downloads * number of users is a big benefit for your user base and a few minutes of your time.
I would say that if you have any deferred loading, CC's cross module code motion is a fear that all of the other existing tools lack and it can get you far far more than 10% reduction of your initial load depending on how your app is written. Generally the larger the app, the more likely transitive dead code will be pulled into the initial download without something like CC.
Care? Sure, we do, but honestly we can probably get that by being smarter with our code atm. Like I said - it's pretty legacy in many (most) areas.
And to be fair - it was much closer to the 10% figure most of the time than the 20. Sometimes less.
Given our kind of unoptimized dev flow (for JS anyhow, we're pretty good overall) it meant that Closure was just... more of a pain in the ass (for many reasons, the JVM didn't help either, yet another moving part).
So we chose dev productivity over it. When our codebase is more streamlined and modern-looking I think we'll re-evaluate and trust me Closure will be on that list.
> have you tried it recently?
About 6 months ago. Was better, just not as smooth a flow and fast as Uglify was. Glad to hear that it's an ongoing effort though.
> My view is generally, it's better to spend time at compile time.
Generally I'd agree... if it wasn't that our dev flow often had to include compiles (due to... reasons I can't get into here). This is a problem we're working to fix on our end but it did make Closure a lot more annoying, unfortunately. We did used to use it, so I'm not talking from a position of not having used it here :)
> Generally the larger the app, the more likely transitive dead code will be pulled into the initial download without something like CC.
Generally agree. However we have a LOT of strange orphan code (that we're clearing up) which means our dead-code was surprisingly low across the project while perhaps still dead code at some specific point of access.
Annoying? Yes. Edge case? Perhaps. I think it's more common in large old projects than any developer would like unfortunately.
Thankfully there is roadmap and we WILL be evaluating Closure when we get further along. Like I said - I used to be the main cheerleader for it here.
It's possible in abrinthebay's scenario, they simply haven't crammed in so many Javascript libraries that the code-stripping can find 10-20% unused code.
(I'm also having a hard time avoiding calling "the code stripper yanks 10-20% of my code" an indicator that one's choice of libraries is wastefully large, but that's a separate thread of debate).
But even in the case where you don't get dead stripping, you'll still get deferred code motion. And even if you don't get deferred code motion, you'll still get better renaming, because with type analysis, you can know which properties are disjoint from others.
At some point the argument gets into the "I don't need a C compiler, because I already write fast, efficient ASM code" territory. If your code base is perfectly gardened, ok, you don't need any compiler tools. The statistically likelihood of that situation remaining stable as your project ages and adds more developers approaches zero IMHO.
... because that's the future.
https://cloud.google.com/solutions/angularjs-cloud-endpoints...
That's just a fancy way of distributing data across services. It's not client-side processing of the data: it's server side.
"MVC frameworks, such as AngularJS, have been developed that enable client-side developers to build powerful and compelling UIs."
"This paper provides best practices and guidance to web developers who are interested in AngularJS or other client-side MVC technologies and want to optimize their server backend for these technologies."
"The growing popularity of client-side MVC frameworks such as Backbone.js and AngularJS is representative of this shift to the client. These frameworks help reduce complexity and increase reuse in even the simplest of applications... As the UI moves to the client, the server becomes simpler."
But I was specifically referring to data processing on the client and while those frameworks obviously can do that the page you linked describes where they farm it out to other cloud services.
This is obviously faster than doing it on the client.. and is exactly what I was talking about.
The future you linked to is the exact opposite of doing data processing on the client. So why you'd call client-side data processing the future with that link as evidence I don't know.
... unless you don't actually understand what "client side" means I guess. Client Initiated Processing !== Clint Side Processing.
3-4X slower than Uglify I could believe, but saying Closure is 60X slower and claiming compression performance I cannot even reproduce with a code base that's 40-50X smaller. What???
I've never seen more than a minute on our codebase for Uglify. It could also be we were doing something stupid with Closure and slowing it down (like stopping then spinning up the JVM for each package for example) which is certainly possible.
However if we add in some of the more computationally heavy Uglify options it will go up somewhat.
[1]: https://github.com/babel/babel/issues/1828 [2]: https://github.com/babel-plugins/babel-plugin-dead-code-elim...
- a better dead code elimination thanks to Static Type System,
- code generations with macro functions,
- inlining of functions, constructors, and objects
- static code analyzer
all this things for all the haxe targets(javascript,flash,php,python,java,c#,c++,neko and work in progress lua)
For me these are of no concern and I'd probably use Haxe had I the right project for it, but for most JS-and-only-JS people it's a deal breaker. I will never be friends with one of those programmers.
It is really a fantastic tool (along with the Closure Library and other members of the Closure family) for anyone that values maintainable, solid JS.
I can understand why it's not more popular; it feels a lot like Java -- industrial strength, non-flashy, and perhaps a little boring. It's also a little hard to setup for a real project (tutorials could be better).
It has been around since the creation of Gmail, and will be around to stay for years to come. (Though it has improved substantially over the years.)