Closure Tools

Using DepsWriter

Introduction

Using ClosureBuilder briefly covered Closure Library's debug loader. When you use the uncompiled source, requiring a namespace with goog.require() fetches that namespace by appending an additional <script> tag whose src attribute is a URL to the script that provides that namespace.

But how does Closure Library know which files provide which namespaces? Included in Closure Library is a default dependency file named deps.js. This file contains one line for every JavaScript file in the library, each specifying the file location (relative to base.js), the namespaces it provides, and the namespace it requires.

In debug mode, a goog.require() statement looks to see if the require namespace was specified and, if so, fetch the files that provide it and all of its dependencies.

However, Closure Library only comes with a dependency file for the namespaces in the library. If you plan to write your own namespaces (and you likely will), you can use depswriter.py to make a dependency file for the namespaces you create.

Dependency file syntax

Dependency files simply register the location of namespaces and the namespaces they depend on, using a function defined in base.js named goog.addDependency(). Here's a simple example from deps.js:

goog.addDependency('dom/forms.js', ['goog.dom.forms'], ['goog.structs.Map']);

This registers the file dom/forms.js, which provides one namespace, goog.dom.forms, and requires one namespace, goog.structs.Map. Note that the path, dom/forms.js, is relative to the directory that base.js is in.

Using DepsWriter

DepsWriter automates the process of writing dependency files by scanning files to find namespaces provided and required with goog.require and goog.provide.

In this example, there are two files, each with a namespace, one of which depends on the other, and both of which depend on namespaces in Closure Library. The goog.provide and goog.require statements at the top might look like this:

goog.provide('myproject.foo');

goog.require('goog.array');
goog.require('goog.dom');
goog.require('myproject.bar');
goog.provide('myproject.bar');

goog.require('goog.string');

myproject.foo depends on myproject.bar. We need to create a single dependency file so that the debug mode loader knows where these files exist.

The dependency file specifies paths relative to base.js. So if base.js and the files that provide myproject.foo and myproject.bar are served at the following URLs

http://<server>/closure/goog/base.js
http://<server>/myproject/foo.js
http://<server>/myproject/bar.js

then the relative paths to foo.js and bar.js are ../../myproject/foo.js and ../../myproject/bar.js. Each .. means "parent directory". The expression ../.. climbs up out of goog and then out of closure.

Generating a dependency file with depswriter.py

We need DepsWriter to write a file that registers both these paths with goog.addDependency(). DepsWriter allows us to specify a directory to scan for .js files, along with a custom prefix, with the --root_with_prefix flag.

$ closure-library/closure/bin/build/depswriter.py  \
    --root_with_prefix="myproject ../../myproject" \
    > myproject-deps.js

This command scans the myproject directory for .js files and writes out a goog.addDependency line for each. The path will be the prefix (here, ../../myproject) combined with the relative path from the root. It assumes we're running from the directory above both the closure-library and myproject directories created in the ClosureBuilder tutorial.

In this case we've written the result into myproject-deps.js with the > operator. You can instead specify an output file using the --output_file flag. DepsWriter produces the following output:

// This file was autogenerated by closure/bin/build/depswriter.py.
// Please do not edit.
goog.addDependency('../../myproject/bar.js', ['myproject.bar'], ['goog.string']);
goog.addDependency('../../myproject/foo.js', ['myproject.foo'], ['goog.array', 'goog.dom', 'myproject.bar']);

This file expresses the same dependency information as the goog.provide() and goog.require() statements in the source code.

Using a generated dependency file in your project

To include a generated dependency file, just include a <script> tag for it, after base.js. After the tag, you can require your newly specified namespaces:

<!doctype html>
<html>
  <head>
    <script src="/closure/goog/base.js"></script>
    <script src="/myproject/myproject-deps.js"></script>
    <script>
      goog.require('myproject.foo');
    </script>
  </head>
  <body>
    <!-- content -->
    <script>
      myproject.foo.start();
    </script>
  </body>
</html>

This code loads myproject.foo (and myproject.bar, by dependency), then calls myproject.foo.start() just before the closing <body> tag.

Note that you should only link to base.js and your dependency files in the debug version of your application. When using compiled JavaScript, just include the script tag to load the compiled file.

Authentication required

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

Signing you in...

Google Developers needs your permission to do that.