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.