Skip to content

Instantly share code, notes, and snippets.

@watilde
Last active December 19, 2015 19:09
Show Gist options
  • Save watilde/6004469 to your computer and use it in GitHub Desktop.
Save watilde/6004469 to your computer and use it in GitHub Desktop.

モダンなモジュラー

高度に分離し、モジュール化された異なる機能を組み合わせてできるアプリケーションのことをモジュラーという

一部に加えた変更による他の部分への影響がきわめてわかりやすくなるので、疎結合化を行うと依存関係が減りメンテナンス性が向上する

今の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";

モジュラーなJavaScriptを実現する3つのフォーマット

  • AMD
  • CommonJS
  • Harmony

AMD

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 () {}
});

AMDすごい

  • 柔軟なモジュールを定義するための方法が整ってる
  • <script>よりも無駄がない
  • モジュール定義が隠蔽されているため、グローバル名前空間の汚染を避ける事ができる
  • ほぼ間違いなく他の方法よりもうまくいく(クロスドメインおk!)
  • 複数のモジュールを一つのファイルに含めるトランスポート手法を提案
  • 遅延ロードもできる

まとめ

グローバルの心配ない 名前付きモジュールがサポートされてる サーバーでの変換が不要 依存性の管理に使うのが楽しい。

CommonJS

// app.js

var modA = requre("./foo");

exports.foo = function () {
    return modA/helloWorld();
};

// foo.js

exports.helloworld = function () {
    return "Hello";
}

Harmony

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment