Closure Libraryを使ったJSファイル間の依存関係の記述 

[Google Closure Library](https://developers.google.com/closure/library/)の依存関係解決ツールは非常に便利。

##Closure Libraryのインストール

- http://code.google.com/p/closure-library/downloads/list

ファイルをダウンロードしたら解凍しアプリケーションのpublicディレクトリに設置する。ここでいうpublicディレクトリに設置するというのは

```
application
`-- public
    `-- javascripts
        |-- closure-library
        |   |-- closure
        |   |   |-- bin
        |   |   |   `-- build
        |   |   |       |-- closurebuilder.py
        |   |   |       `-- depswriter.py
        |   |   `-- goog
        |   |       `-- base.js
        |   `-- third_party
        `-- myapp
            |-- base.js
            `-- main.js
```

のようになっているとしてpublicディレクトリ以下のファイル間のファイルシステム上での相対位置とURIとしての相対位置が同じになることを意味する。

##依存関係の記述

Railsのassetsパイプラインにはファイル間の依存関係を書く事ができるが、Closure Libraryではファイル単位ではなくObject単位での依存関係を記述することができる。

使うのは`goog.provide`と`goog.require`。これら自体は`closure-library/closure/goog/base.js`に定義されている。一つのファイルが提供・要求するオブジェクトの数に制限は無い。

```js
// base.js
goog.provide('app') // 提供するオブジェクトの宣言

var app = {}

app.version = 1
```

```js
// main.js
goog.provide('app.run') // 提供するオブジェクトの宣言

goog.require('app') // 必要とするオブジェクトの宣言

var app;

app = app || {};

app.run = function() {
  alert(app.version) // => 1
}
```

##依存ファイルの生成

`goog.provide`と`goog.require`から依存関係を抽出する。これにはdepswriter.pyというスクリプトを使う。通常この結果をdeps.jsという名前で保存する。(Closure Library内部の依存関係はclocure-libaray/closure/goog/deps.jsに保存されており、goog/base.jsが読み込まれると自動でこちらも読み込まれるようになっている。)

```sh
% python public/javascripts/closure-library/closure/bin/build/depswriter.py \
  --root_with_prefix='public/javascripts/myapp ../../../myapp' \
  --output_file=public/javascripts/myapp/deps.js
```

`root_with_prefix`オプションで自分のJSコードの絶対パスとgoog/base.jsからの相対パスを指定する。間にスペースが一つ入っているのに注意。この指定されたディレクトリ以下のファイルが全て調べられ`output_file`ディレクトリに結果が保存される。

今回の場合deps.jsは次のようになる

```js
// This file was autogenerated by public/javascripts/closure/bin/build/depswriter.py.
// Please do not edit.
goog.addDependency('../../../myapp/base.js', ['app'], []);
goog.addDependency('../../../myapp/main.js', ['app.run'], ['app']);
```

##ブラウザで実行する(開発時)

goog/base.jsと先ほど作ったdeps.jsと起点となるファイルを読み込む

```html
<!DOCTYPE html>
<html>
  <head>
    <title>myapp</title>
  </head>
  <body>
    <script src="javascripts/closure-library/closure/goog/base.js"></script>
    <script src="javascripts/myapp/deps.js"></script>
    <script src="javascripts/myapp/main.js"></script>
    <script>
      window.onload = app.run
    </script>
  </body>
</html>
```

この場合main.jsが読み込まれるとClosure Libraryが自動的に依存しているbase.jsを読み込む。

##ソースコードを一つにまとめる

本番環境ではソースコードを一つにまとめたい。この用途にはclosurebuilder.pyを使う

```sh
% python public/javascripts/closure-library/closure/bin/build/closurebuilder.py \
  --root=public/javascripts \
  --namespace=app.run \
  --output_file=public/javascripts/myapp.js \
  --output_mode=script
```

`namespace`オプションで起点となるオブジェクトを指定する。今回ならmain.jsに提供しているので、このファイルを起点にして依存するファイルをまとめていく。
myapp.jsというJSファイルが生成されているので、これをブラウザで読みこめばいい。下記はファイルの読み込みが一回で済む分だけ、前の例より効率がいい。

```html
<!DOCTYPE html>
<html>
  <head>
    <title>myapp</title>
  </head>
  <body>
    <script src="javascripts/myapp.js"></script>
    <script>
      window.onload = app.run
    </script>
  </body>
</html>
```

##ソースコードを圧縮する

JSファイルを圧縮するツールはいくつかあるが、ここでは[Google Closure Compiler](http://code.google.com/closure/compiler/)を使う。ダウンロードして解凍すると中にcompiler.jarがあるので適当な場所に設置する。上で使ったclosurebuilder.pyにはオプションでコンパイル時にClosure Compilerで圧縮するオプションがある。

```sh
% python public/javascripts/closure-library/closure/bin/build/closurebuilder.py \
  --root=public/javascripts \
  --namespace=app.run \
  --output_file=public/javascripts/myapp.js \
  --output_mode=compiled \
  --compiler_jar=path/to/compiler.jar \
  --compiler_flags='--compilation_level=ADVANCED_OPTIMIZATIONS'
```

`compiler_jar`オプションで先程のcompiler.jarを指定する。`compiler_flags`は圧縮レベルで`WHITESPACE_ONLY` `SIMPLE_OPTIMIZATIONS` `ADVANCED_OPTIMIZATIONS`の三つの中から選ぶ。