Revision 2 as of 2011-11-14 05:41:46

Clear message
Locked History Actions

Closure_Library/depswriter

DepsWriterを使う

イントロダクション

ClosureBuilderを使うでは、簡単にClosure Libraryのデバッグローダについて触れた。

コンパイルされていないソースを使う場合、goog.require()によってnamespaceが要求されフェッチされるが、それはそのnamespaceを供給するスクリプトのURLをsrcとする<script>タグが追加されることによって行われる。

しかし、Closure Libraryは、そのnamespaceを供給するファイルをどのようにして知ることができるのだろうか。 Closure Libraryにはdeps.jsという名前のデフォルト依存ファイルが含まれる。 このファイルには、ライブラリ中のすべてのJavaScriptファイルが行として記述され、それぞれの行は(base.js相対での)ファイルの位、それが供給するnamespace、それが要求するnamespaceが記述されている。

デバッグモードでは、goog.require()文が要求するnamespaceがもしあればそれを供給するファイルとそのすべての依存をフェッチする。

しかし、Closure Libraryは、そのライブラリについてだけの依存ファイルしか持ちあわせていない。 もし君が自身のnamespaceを作ろうとするなら(確実にそうするだろうが)、君が作成するnamespaceについてdepswriter.pyを使って依存ファイルを作成しなければならない。

依存ファイルの構文

依存ファイルは、base.js中のgoog.addDependency()という関数を使って単純にnamespaceの場所とそれが依存するnamespaceを記述したものである。以下に単純な例を示そう。

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

これはdom/forms.jsというファイルを登録するものだが、goog.dom.formsというnamespaceを供給し、goog.struicts.Mapというnamespaceを要求するものだ。dom/forms.jsというパスはbase.jsからの相対であることに注意。

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_mode 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.