Google Closure Tools
and ClojureScript
Thomas Allen, Senior Developer at Wikidocs
(thomas@oinksoft.com)
July 10, 2014
Sacramento Google Developer Group
VSP Vision Care, Rancho Cordova, CA
## What are the Closure Tools?
* Google's frontend toolchain: Integrated tools for HTML, CSS,
JavaScript development
* Used to create Gmail, Google Maps, Google Docs, etc.
* Open-sourced in 2009
Overview: [https://developers.google.com/closure/](https://developers.google.com/closure/)
## The Tools
* **Compiler**: Advanced JavaScript compressor/optimizer
* **Library**: Google's JavaScript standard library
* **Templates**: Compiles Soy templates to Java classes and JavaScript functions
* **Stylesheets**: Compiles GSS to optimized CSS
* **Linter**: JavaScript static analysis tool
## Closure Compiler
* Java-based JavaScript compiler.
* Advanced optimizations:
* Eliminates "dead" code
* Flattens property paths: `foo.bar.baz` may become `fBZ`
* Inlines arithmetic, optimizes loops, conditionals
* Targets small compressed code size and high performance
* Extensible (pass architecture)
## Closure Library
* Comprehensive JavaScript library
* Dependency management via Compiler
* DOM manipulation
* Network (XHR, `IFRAME`s, WebSockets, etc.)
* Data structures and other utilities
* User interface components
* Fast and portable, works in old IE. Reflects Google products'
browser support
## Closure Linter
* JavaScript static analysis tool
* Enforces specific Google code standards
* Difficult to use productively
## Documentation
![](oreilly.png)
* Closure Library has thorough API docs and demos
* End-user documentation is sparse
* _Closure, The Definitive Guide_ by Michael Bolin (O'Reilly 2011) is
essential.
## Pros and Cons: Pros
* Performant, powerful, heavily-tested library
* JS compiler has best compression and performance optimization
* Integrated toolchain for building small static assets
* Excellent internationalization support
## Pros and Cons: Cons
* Advanced compiler optimizations break stuff
* Heavy Java tools and sophisticated compiler create slow builds
* Verbose library API
* Parts of the library are difficult to reuse (may have hard-coded
Google URLs, for instance)
* Closure Stylesheets, Templates are very limited
* Tools can only be extended via Java APIs
## The Future
* All Closure Tools projects are active
* All are used outside of Google
* Projects using the entire toolchain are rare
* Google's Dart language attempts to replace Closure Tools
* ClojureScript projects depend on the compiler and use the library
## Dart and Closure
> FAQ: What happened to JSPrime?
>
> The JSPrime effort was begun to unify and be a (single!) successor
> to GWT and Closure/JSCompiler, suitable for large-scale development
> inside and outside Google, including being amenable to IDE-like
> tools and static compiler optimizations. The JSPrime team is happily
> folding its efforts into Dash now that everyone agrees Dash will
> explicitly include the same goals.
>
> \- Google, "Future of Javascript", 2010
## Dart and Closure (2)
> FAQ: What about the existing code bases for large Google Apps?
> Won’t they have to rebuild everything to take advantage of Dash?
>
> The Dash Cross Compiler should be capable of taking typed Closure
> code (with some restrictions) and converting to Dash. Although the
> migration process won’t be fully automatic, it should make moving
> over to a Dash codebase somewhat easier.
>
> \- Google, "Future of Javascript", 2010
## ClojureScript and Closure
* ClojureScript released in Spring 2011
* Depends on Closure Compiler
* Core written with Closure Library
* Easy way to get started with Closure Library
ClojureScript and Closure (A)
Closure:
goog.provide('mylib.urls');
goog.require('goog.Uri');
mylib.urls.domain = function(url) {
return new goog.Uri(url).getDomain();
};
ClojureScript:
(ns mylib.urls
(:import [goog.net Uri]))
(defn domain [url]
(.getDomain (Uri. url)))
ClojureScript and Closure (B1)
Closure:
goog.provide('mylib.app');
goog.require('goog.dom'):
goog.require('goog.ui.Tab');
goog.require('goog.ui.TabBar');
/** @export */
mylib.app.main = function() {
var rootEl = goog.dom.getElement('tabs'),
tabBar = new goog.ui.TabBar();
tabBar.addChild(new goog.ui.Tab('Tab #1'), true);
tabBar.addChild(new goog.ui.Tab('Tab #2'), true);
tabBar.addChild(new goog.ui.Tab('Tab #3'), true);
tabBar.render(rootEl);
};
ClojureScript and Closure (B2)
ClojureScript:
(ns mylib.app
(:require [goog.dom :as dom])
(:import [goog.ui Tab TabBar]))
(defn ^:export main []
(let [root-el (dom/getElement "tabs")]
(doto (TabBar.)
(.addChild (Tab. "Tab #1") true)
(.addChild (Tab. "Tab #2") true)
(.addChild (Tab. "Tab #3") true)
(.render root-el))))
##ClojureScript Caveats
* Painful to implement mutable data structures
* JavaScript interop is awkward:
`KeyHandler.EventType.KEY` →
`(.-KEY (KeyHandler/EventType))`
* Build times go from painfully slow to agonizingly slow if you use
too much Clojure tooling
##Alternatives
* Plovr: [http://plovr.com/](http://plovr.com/)
* Many in NPM! [https://www.npmjs.org/search?q=closure%20tools](https://www.npmjs.org/search?q=closure%20tools)
* Use `closurebuilder.py` and something like Make: [https://developers.google.com/closure/library/docs/closurebuilder](https://developers.google.com/closure/library/docs/closurebuilder)