Closure Tools

Using ClosureBuilder

Getting Started with the Closure Library illustrates how to start working with Closure Library in your project. This article outlines how to use ClosureBuilder and Closure Compiler with your project to shrink your files into one, small, minimized JavaScript file.

Why closurebuilder.py?

If you did the Hello World exercise in Getting Started with the Closure Library, you may have noticed that the browser made several HTTP requests during page load. For each Closure Library file required by goog.require(), a new script tag is created to load the file. Each Closure Library file is loaded as a separate HTTP request.

This works well for development, since one can see the uncompiled source and use existing debugging tools. But it's not good for serving to users. Loading all these files individually is unnecessary and slow.

For a live application serving to real users, you're going to want to serve a "compiled" version of your app. Closure Compiler takes your code and the required Closure Library files, strip comments, does some optimizations, and creates one larger file as output. Your server can then just serve that one file rather than many individual files.

The closurebuilder.py tool, located in closure/bin/build, is a tool to help build compiled JavaScript files. It scans your files and the Closure Library files and can calculate orderings of script files in dependency order. It can output either the scripts' filenames or their contents in dependency order, or can pass the files along to the Closure Compiler to produce a compiled version.

Resolving Closure Library Dependencies with closurebuilder.py

This example uses closurebuilder.py to generate a single script file containing everything the script needs.

If you haven't already done so, follow the instructions in Getting Started with the Closure Library to download and unpack the Closure Library. In the directory in which you saved closure-library, create a directory myproject for your new project.

In the myproject directory, make a start.js file containing the following code.

goog.provide('myproject.start');

goog.require('goog.dom');

myproject.start = function() {
  var newDiv = goog.dom.createDom('h1', {'style': 'background-color:#EEE'},
    'Hello world!');
  goog.dom.appendChild(document.body, newDiv);
};

// Ensures the symbol will be visible after compiler renaming.
goog.exportSymbol('myproject.start', myproject.start);

In the same directory, make a a simple HTML file named myproject.html to run this script.

<!doctype html>
<html>
  <head>
    <script src="../closure-library/closure/goog/base.js"></script>
    <script src="start.js"></script>
  </head>
  <body>
    <script>
      myproject.start();
    </script>
  </body>
</html>

When you load this page in a browser, you should see the message "Hello world!"

Calculating dependencies

Execute the following command from the directory containing both the closure-library and myproject directories.

closure-library/closure/bin/build/closurebuilder.py \
  --root=closure-library/ \
  --root=myproject/ \
  --namespace="myproject.start"

Note: these tools are executable Python scripts and are set to be interpreted with /usr/bin/env on UNIX systems. If you're using Windows, see Python's documentation on running Python programs on Windows.

The output should look like this (this is combined stdout and stderr):

closure-library/closure/bin/build/closurebuilder.py: Scanning paths...
closure-library/closure/bin/build/closurebuilder.py: 596 sources scanned.
closure-library/closure/bin/build/closurebuilder.py: Building dependency tree..
closure-library/closure/goog/base.js
closure-library/closure/goog/debug/error.js
closure-library/closure/goog/string/string.js
closure-library/closure/goog/asserts/asserts.js
closure-library/closure/goog/array/array.js
closure-library/closure/goog/dom/classes.js
closure-library/closure/goog/object/object.js
closure-library/closure/goog/dom/tagname.js
closure-library/closure/goog/useragent/useragent.js
closure-library/closure/goog/math/size.js
closure-library/closure/goog/math/coordinate.js
closure-library/closure/goog/dom/dom.js
myproject/start.js

What is this doing?

Each --root flag tells ClosureBuilder to scan that directory for .js files. Each file is scanned for goog.provide and goog.require statements, which indicate that the file provides a namespace or requires a namespace provided in another file.

Scanning all files allows ClosureBuilder to build an in-memory dependency tree of all namespaces. The --namespace flag tells ClosureBuilder to start with the myproject.start namespace in that tree and get all of its dependencies. By default, it outputs the results as a list of files, in dependency order. For every file in the list, every required namespace is provided by another file that appears earlier in the list.

Shrinking Code with ClosureBuilder and the Closure Compiler

To get a compiled and minified version of your code, use the --output_modeClosure Compiler documentation.

To get compiled output, you'll need the Closure Compiler executable jar file and you'll need to tell ClosureBuilder where it is. Download the jar from the repository and put it in the same directory that contains your closure-library directory.

Re-run closurebuilder.py with two additional flags to request compiled output and to indicate the location of compiler.jar.

closure-library/closure/bin/build/closurebuilder.py \
  --root=closure-library/ \
  --root=myproject/ \
  --namespace="myproject.start" \
  --output_mode=compiled \
  --compiler_jar=compiler.jar \
  > myproject/start-compiled.js

ClosureBuilder writes the compiler's output to standard out. Here, we're piping it into a file named start-compiled.js. Alternatively, you can specify a file to write to using the --output_file flag (this may be easier if you're unfamiliar with Unix-style piping).

Put start-compiled.js next to myproject.html and modify the HTML file to instead use the compiled version:

<!doctype html>
<html>
  <head>
    <script src="start-compiled.js"></script>
  </head>
  <body>
    <script>
      myproject.start();
    </script>
  </body>
</html>

This file behaves the same as your original code, but it can be downloaded as one small JavaScript file.

Using ClosureBuilder in web servers and build systems

Generally, developers using Closure Library implement the ability to serve in debug and compiled modes.

  • In debug mode, the server serves the uncompiled files. In the HTML, the head tag includes script tags that point at Closure Library's base.js and the project .js files, as in the example above. There may also be additional dependency files as described in the DepsWriter documentation.
  • In compiled mode, the server does not serve the uncompiled files. In the head tag, there is just one script tag that points at the compiled JavaScript file, as in the example above.

The served web page should have the appropriate <script> tags for each mode.

It's much easier to work with uncompiled code when developing. You can edit and save your files and reload to see changes. Errors give correct line numbers and you can use in-browser debuggers with uncompiled, unobfuscated source.

But when serving your application, the compiled version is preferable. Compiled output loads quickly and speed is very important when you serve to users. The compiler optimizes the size of the JavaScript and puts it in one small file rather than many uncompiled files.

Use in a build system

ClosureBuilder is provided as a standalone command-line tool so that it can be incorporated into different build systems. You can set up ClosureBuilder's output to be a step in your build system.

Additional flags to Closure Compiler

Closure Compiler takes its own additional flags for particular features, so ClosureBuilder has a way of specifying flags to pass along to the compiler. This can be done using the --compiler_flags flag. For example, we can tell the compiler to use its advanced optimization mode by including this additional flag:

closure-library/closure/bin/build/closurebuilder.py \
  --root=closure-library/ \
  --root=myproject/ \
  --namespace="myproject.start" \
  --output_mode=compiled \
  --compiler_jar=compiler.jar \
  --compiler_flags="--compilation_level=ADVANCED_OPTIMIZATIONS" \
  > start-compiled.js

See Advanced Compilation and Externs in the Closure Compiler documentation for more information about using ADVANCED_OPTIMIZATIONS.

ClosureBuilder option reference

There are other options for ClosureBuilder that aren't documented here. You can always get a full list by using the --help flag.

closure-library/closure/bin/build/closurebuilder.py --help

For convenience, the output is copied here:

$ closure/bin/build/closurebuilder.py --help
Usage: Utility for Closure Library dependency calculation.

ClosureBuilder scans source files to build dependency info.  From the
dependencies, the script can produce a deps.js file, a manifest in dependency
order, a concatenated script, or compiled output from the Closure Compiler.

Paths to files can be expressed as individual arguments to the tool (intended
for use with find and xargs).  As a convenience, --root can be used to specify
all JS files below a directory.

usage: closurebuilder.py [options] [file1.js file2.js ...]


Options:
  -h, --help            show this help message and exit
  -i INPUTS, --input=INPUTS
                        One or more input files to calculate dependencies for.
                        The namespaces in this file will be combined with
                        those given with the -n flag to form the set of
                        namespaces to find dependencies for.
  -n NAMESPACES, --namespace=NAMESPACES
                        One or more namespaces to calculate dependencies for.
                        These namespaces will be combined with those given
                        with the -i flag to form the set of namespaces to find
                        dependencies for.  A Closure namespace is a dot-
                        delimited path expression declared with a call to
                        goog.provide() (e.g. "goog.array" or "foo.bar").
  --root=ROOTS          The paths that should be traversed to build the
                        dependencies.
  -o OUTPUT_MODE, --output_mode=OUTPUT_MODE
                        The type of output to generate from this script.
                        Options are "list" for a list of filenames, "script"
                        for a single script containing the contents of all the
                        files, or "compiled" to produce compiled output with
                        the Closure Compiler.  Default is "list".
  -c COMPILER_JAR, --compiler_jar=COMPILER_JAR
                        The location of the Closure compiler .jar file.
  -f COMPILER_FLAGS, --compiler_flags=COMPILER_FLAGS
                        Additional flags to pass to the Closure compiler.
  --output_file=OUTPUT_FILE
                        If specified, write output to this path instead of
                        writing to standard output.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.