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 Templates

  • Compile "Soy" templates to Java and JS
    {template .session}
      <div class="session">
        {if $user}
          Hi, {$user.firstName} {$user.lastName}!
          <a href="/logout">Sign Out</a>
        {else}
          <a href="/login">Sign In</a>
        {/if}
      </div>
    {/template}
  • Supports internationalization
  • Custom tags and filters via Java API

Closure Stylesheets

  • Compiles Google StyleSheets (GSS) to CSS:
    @def PRIMARY_COLOR rgb(0, 0, 255)
    
    h1 {
      color: PRIMARY_COLOR;
    }
    
    .some-verbose-classname {
      margin-top: 0;
      margin-right: 1em;
      margin-bottom: 20px;
      margin-left: 1em;
    }
  • Combines common styles
  • Shortens CSS class names
## 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)
#Q&A