8 ms·
Closure Compiler: a tool for making JavaScript download and run faster
- eltaco 11y agoBabel is working on minification[1] /dead code elimination [2] as well now [1]: https://github.com/babel/babel/issues/1828 https://github.com/babel/babel/issues/1828 [2]: https://github.com/babel-plugins/babel-plugin-dead-code-elimination https://github.com/babel-plugins/babel-plugin-dead-code-elim...
- Drakim 11y agoHow 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']();
- lclemente 11y agoThey explain it here: https://developers.google.com/closure/compiler/docs/limitations https://developers.google.com/closure/compiler/docs/limitati...
- sgrove 11y agoYou 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.
- rav 11y agoThis kind of indirection is specifically not supported even with simple optimizations: https://developers.google.com/closure/compiler/docs/limitations#restrictions-for-simple_optimizations https://developers.google.com/closure/compiler/docs/limitati...
- dahart 11y agoYou 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.
- reitzensteinm 11y agoYou 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.
- teamhappy 11y agofunction add(a,b) { return a+b } console.log(add(1,2)) Compiles to console.log(3) I'm not sure about your example, but I think it would work. (Apparently not)
- mythz 11y agoHave a look at the advanced compilation option: https://developers.google.com/closure/compiler/docs/api-tutorial3?hl=en https://developers.google.com/closure/compiler/docs/api-tuto... 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: p['removeAttr'] = function(name){ return this['each'](function(){ if (this.nodeType == 1) this.removeAttribute(name); }); }; Which closure advanced rewrites to: q.removeAttr=function(a){return this.each(function(){this.removeAttribute(a)})}; Original: https://github.com/mythz/jquip/blob/master/dist/jquip.all.js https://github.com/mythz/jquip/blob/master/dist/jquip.all.js Compiled: https://github.com/mythz/jquip/blob/master/dist/jquip.all.closure-advanced.js https://github.com/mythz/jquip/blob/master/dist/jquip.all.cl...
- nunull 11y agoMay i ask why you are using this notation? I honestly can't think of any benefits. Isn't it more convenient and readable to use `p.removeAttr`?
- mythz 11y agoMy comment explains the entire purpose for using it - if I didn't, it would've got rewritten into `a.b` and none of the public API's would work!
- eschutte2 11y agoI wish there were a better way to indicate which properties were renameable, because I need this too and I'm not willing to go as far as you did.
- Shebanator 11y agothere is a much better way to deal with this: https://developers.google.com/closure/compiler/docs/api-tutorial3#externs https://developers.google.com/closure/compiler/docs/api-tuto...
- dahart 11y agoThe 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. 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-tutorial3#separately 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!
- nickik 11y agoIn ClojureScript there is a attempted going to make Closure Compiler Modules work with other modules: https://github.com/clojure/clojurescript/wiki/Google-Summer-of-Code-2015 https://github.com/clojure/clojurescript/wiki/Google-Summer-...
- swannodette 11y agoThe 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).
- sgrove 11y agoI 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-movement/ 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.
- _jack_ 11y agoBIG NEWS
- kruhft 11y agoI 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.
- DenisM 11y agoAnyone wants to compare this with TypeScript? I'm using Visual Studio for the backend, in case it matters.
- deleted 11y ago[deleted]
- swannodette 11y agoGoogle 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 https://gist.github.com/swannodette/aad077de18309a08cff3
- Scarbutt 11y agoWhy 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.
- drcode 11y agoYou 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.
- thomasfoster96 11y agoThe 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.
- dkarapetyan 11y agoHuh? 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?
- thomasfoster96 11y agoWell 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.
- cromwellian 11y ago
- pkmiec 11y agohow does this compare to uglifier?
- tomjen3 11y agoBeats 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).
- abritinthebay 11y agoDifferent 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. Choose the right tool for the job and all that.
- adrianh 11y agoI've been using Closure Compiler with ADVANCED_OPTIMIZATIONS (which does the dead-code removal) for soundslice.com for several years. It is truly awesome! Check out 39:30 in my 37signals talk at http://37signals.com/talks/soundslice 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.
- abritinthebay 11y agoHaving 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.
- hellofunk 11y agoThere 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.
- abritinthebay 11y agoI'm not saying our code base is particularly small or well suited for CC, just that in my case it was pretty poorly performing.
- hellofunk 11y agoAfter seeing you have millions of lines of code, now I understand how 10 minutes could be possible. You should have led with that :)
- swannodette 11y ago10 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.
- sa_su_ke_hx 11y agowith haxe you can have the same effect but with: - 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)
- klibertp 11y agoBut, 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.
- paulddraper 11y agoI 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.)