高度に分離し、モジュール化された異なる機能を組み合わせてできるアプリケーションのことをモジュラーという
一部に加えた変更による他の部分への影響がきわめてわかりやすくなるので、疎結合化を行うと依存関係が減りメンテナンス性が向上する
今のJavaScriptのイテレーションであるECMA-262では、モジュールのコードをインポートする方法は提供されていない
今までに学んだモジュールパターン、オブジェクトリテラルパターンに頼るのも良いが、名前の衝突を招く可能性がある
根本的な解決には、JavaScriptの次のバージョンになるというES Harmonyに導入される予定 http://wiki.ecmascript.org/doku.php?id=harmony:modules
module "foo" {
export let x = 42;
}
import { y } from "foo";
- AMD
- CommonJS
- Harmony
Asynchronous Module Definition: 非同期モジュール定義
Dojo, MooTools, Firebug, jQueryで採用されている
CommonJSのモジュールフォーマットのドラフトしようとして誕生したが、合意には至らずamdjs groupに移された
AMDでは、モジュールとそのモジュールに依存する他のモジュールの両方を非同期に読み込めるような定義が提案されている
利点 モジュール間の密結合を非同期性と高い柔軟性によって取り除ける
define(
module_id, /* 省略可 */
[dependencies], /* 省略可 */
definition function /* モジュールやオブジェクトをインスタンス化するための関数 8?
);
module_idは、非AMDの連結ツールを利用している時だけ必要なオプション引数で、値が設定されていないときは無名モジュールと呼ぶ
無名モジュールを扱う場合、module_idの基本的な考え方はDRY
dependencies引数は定義中のモジュールが影響を受ける依存モジュールの配列を表している
その次の引数には澪ジュールのインスタンス化を実行する関数を設定する
define("myModule",
["foo", "bar"],
function (foo, bar) {
var myModule = {
doStuff: function () {
console.log(Yo! Stuff!");
}
};
return MyModule;
}
);
requireはトップレベルのJavaScriptファイルやモジュールの中にコードを読み込むときに使われる
require(["foo", "bar"], function (foo, bar) {
foo.doSomthing();
});
依存モジュールを動的に読み込むコードの例
define(function (require) {
var isReady = true;
require(["foo", "bar"], function (foo, bar) {
isReady = true;
foobar = foo() + bar();
});
return {
isReady: isReady,
foobar: foobar
};
});
AMD互換のプラグイン定義
define(["./templates", "text!./template.md", "css!./template.css"],
function(templates, template) {
console.log(templates);
}
);
RequireJSを利用してAMDモジュールの読み込み
require(["app/myModule"],
function(myModule) {
var module = new myModule();
module.doStuff();
}
);
遅延ロード
define(["lib/Deferred"], function (Deferred) {
var defer = new Deferred();
require(["lib/templates/?index.html", "lib/data/?stats"],
function(template, data) {
defer.resolce({template: template, data:data});
}
);
return defer.promise();
});
Dojoとばし
jQueryを使ったAMDモジュール
define(["js/jquery.js", js/jquery.color.js", "js/underscore.js"],
function($, colorPlugin, _) {
var shuffleColor = _.first(_.shuffle(["#666", "#333", "#111"]));
$(".item").animate({"backgroundColor": shuffleColor});
return {};
});
これだと登録という概念が欠けてる
jQUery1.7以降だと非同期モジュールとして登録できるようになった
var jQuery = this.jQuery || "jQuery",
$ = this.$ || f"$",
originaljQuery = jQuery,
original$ = $;
define(["jquery"], function($) {
$(".item").css("background", "greeeeen");
return function () {}
});
- 柔軟なモジュールを定義するための方法が整ってる
- <script>よりも無駄がない
- モジュール定義が隠蔽されているため、グローバル名前空間の汚染を避ける事ができる
- ほぼ間違いなく他の方法よりもうまくいく(クロスドメインおk!)
- 複数のモジュールを一つのファイルに含めるトランスポート手法を提案
- 遅延ロードもできる
グローバルの心配ない 名前付きモジュールがサポートされてる サーバーでの変換が不要 依存性の管理に使うのが楽しい。
// app.js
var modA = requre("./foo");
exports.foo = function () {
return modA/helloWorld();
};
// foo.js
exports.helloworld = function () {
return "Hello";
}