レイヤーとは
Dojoのビルドにおいて、依存関係のあるすべてのモジュールを一つのファイルにまとめたものをレイヤーと呼んでいます。ビルドの結果生成される、dojo.js、dijit.js、myLayer.jsなどがレイヤー・ファイルで、コメントなどが取り除かれて圧縮されています。レイヤー・ファイルは、次のように<script>タグを使って読み込むことができます。
<html> <head> <script type="text/javascript" src="/js/dojo/dojo.js"></script> <script type="text/javascript" src="/js/dijit/dijit.js"></script> <script type="text/javascript" src="/js/acme/myLayer.js"></script> ....
また、dojoのクラス名と意図的に同名のレイヤー・ファイルを作成することも可能です。例えば、acme.myWidgetというクラス(およびそれが依存するモジュール)を含むレイヤー・ファイルを、acme/myWidget.jsとして作成したとします。その場合は、dojo.require("acme.myWidget")によってレイヤー・ファイルをロードすることができます。もちろん、前述のような<script>タグを使って読み込んでも構いません(余談ですが"acme"は架空の会社を意味するスラングで、dojoのドキュメントにはしばしば登場します)。
Dojoのビルドでは、取り込まれるモジュールが重複しないように各レイヤー・ファイルを生成できるようになっているのが特徴です。すなわち、例えばdojo.jsレイヤーにはdojoの基本モジュール群が含まれているとします。次のdijit.jsレイヤーには、dijitに依存する全モジュール群のうち、dojo.jsレイヤーには含まれていないものが取り込まれます。さらに次のmyLayer.jsレイヤーでは、自分のアプリケーションに依存する全モジュール群のうち、dojo.jsレイヤーにもdijit.jsレイヤーにも含まれていないものが取り込まれます。このようにして、同一モジュールを重複してロードすることがないようにしています。
また、dojo.require()は指定されたモジュールがすでにロード済みかどうかをチェックするので、レイヤーとしてすでにロードされたモジュールに対してdojo.require()を呼び出しても不要なリクエストが発行されることはありません。従って、ビルドをする・しないに応じてdojo.require()を変更する必要はありません。
プロファイル
ビルドを行うには、どこにあるどのモジュールをどのレイヤー・ファイルに含めるかといった設定が必要であり、それをプロファイルと呼び、その設定ファイルをプロファイル・ファイルと呼びます。ファイル名は、name.profile.js のように任意の名前の後ろに.profile.jsが付きます。
プロファイルの構造
プロファイル・ファイルの内容は、次に示すようにdependenciesという名前の一つのJavaScriptオブジェクトの定義です。dependenciesオブジェクトは、layersとprefixesというオブジェクトをプロパティとして持ち、それぞれレイヤーとプレフィックスの設定となっています。
dependencies = {
layers: [
// レイヤーの設定
],
prefixes: [
// プレフィックスの設定
]
}
プロファイルの例
以下にプロファイルの具体例を示します。このプロファイルを使ってビルドを行うと、dojo.js、myCalendar.js、myDatePicker.jsの3つのレイヤー・ファイルが生成されます。myDatePickerは単独で使われることはなく、myCalendarウィジェットから実行時に必要になった時点で動的に呼び出されるモジュールであると仮定します。以下、コメントの番号ごとに解説します。
dependencies = {
stripConsole: "normal", // (1)
layers: [ // (2)
{
name: "dojo.js", // (3)
dependencies: [ // (4)
"dojo.parser",
"dijit._Widget"
]
},
{
name: "../acme/widget/myCalendar.js", // (5)
dependencies: [ // (6)
"acme.widget.myCalendar",
"acme.data.myDataStore"
]
},
{
name: "../acme/widget/myDatePicker.js", // (7)
layerDependencies: [ // (8)
"myCalendar.js"
],
dependencies: [ // (9)
"acme.widget.myDatePicker"
]
}
],
prefixes: [ // (10)
[ "dijit", "../dijit" ],
[ "acme", "../acme" ]
]
}
- console.log()やconsole.debug()などの呼び出しを削除するオプションを指定しています。"normal"を指定すると、console.error()とconsole.warn()以外のすべてのconsole.*呼び出しを削除します。"all"を指定すると、すべてのconsole.*呼び出しを削除します。
- ここでは3つのレイヤー、dojo.js、myCalendar.js、myDatePicker.jsを定義しています。
- dojoコアのレイヤーです。dojoローダーをはじめ、dojoの基本モジュールが自動的に取り込まれます。
- ここではdojoの基本モジュールに加え、dojo.parserとdijit._Widgetも依存関係に加えることでdojo.jsに取り込むことを指示しています。dojo.parserとdijit._Widgetがさらに依存するモジュールがあればそれらも再帰的に取り込まれます。
- myCalendar.jsのレイヤーです。本来、name: "myCalendar.js"のように指定すればdojo.jsと同じフォルダにmyCalendar.jsが生成され、<script>タグを使って読み込むことができます。ここではあえてmyCalendarクラスと同じ場所にレイヤー・ファイルのmyCalendar.jsが上書き作成されるように指定しています。これにより、dojo.requireによってビルド結果であるレイヤー・ファイルのmyCalendar.jsを読み込めるようになります。
- myCalendar.jsレイヤーが依存するモジュールを列挙します。ビルド・ツールはソース・コード内のdojo.require()を参照して再帰的に依存関係を調べてそれらをすべてレイヤーに取り込むので、最上位レベルのモジュールだけを列挙します(※2)。
- myDatePicker.jsのレイヤーです。
- この例では、myDatePickerはmyCalendarウィジェットから動的に呼び出されると仮定しているので、このレイヤーにはmyCalendar.jsレイヤーにすでに取り込まれているモジュールは含める必要がありません(もし含めると、同じモジュールを2回ロードすることになり、無駄になります)。そのような場合は、layerDependenciesで依存するレイヤーを指定します。こうすることにより、myDatePickerが依存するモジュール群のうちで、myCalendarには依存していないモジュールだけが取り込まれます。
- myDatePicker.jsレイヤーが依存するモジュールを列挙します。
- モジュールのプレフィックスをキーとして、それらのファイルの置き場所を指定します。dojo.jsのあるdojoフォルダからの相対パスで指定します。
基本的にここで列挙された順にレイヤーに取り込まれます。また、列挙されたモジュールが依存モジュール(dojo.require()で指定されているモジュール)を持つ場合は、依存モジュールから先に取り込まれます。依存関係ツリーの末端から順に評価が行われ、最後に最上位レベルのモジュールが評価されるようにするためです。それによりサブクラスを定義する時点でベース・クラスが未定義といった事態が起こらないことを保証しています。
ビルドの実行例
リスト3のプロファイルをutil/buildscripts/profiles/cal.profile.jsとして保存します。すると、次のようにしてビルドを実行することができます。
> cd util/buildscripts > build profile=cal action=release
releaseフォルダにビルド結果が生成されます。release/dojo/dojo/build.txtを開いて、プロファイルに指定した通りのモジュールが各レイヤーに取り込まれているか確認するとよいでしょう。
