Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

RequireJS 2.0による依存関係の明示、フォールバック、複数バージョンの混在

旧ブログのRequireJSネタがひそかにブクマされつづけているので需要があるかなと思い、最近調査したバージョン2.0の機能についてまとめます。元ネタはこちらです。

依存関係の明示

従来のバージョンでjQueryプラグインを利用するには、RequireJS用のorderプラグインを使って読み込み順序を指定する必要がありました。jQueryプラグインが先に読み込まれると「jQueryなんて見つからねーよ!」と言われてしまうためです。これはjQueryに限らず様々なフレームワーク・ライブラリで起こりうる一般的な問題と言えます。

define('order!jquery', 'order!jquery.someplguin'], function($) {
  // ...
});

もちろんプラグイン自身がjQueryへの依存を明示している場合は以下のように簡潔に書けるのですが、多くの場合はプラグインのコードに手を加える必要がありいろいろと面倒でした。

define('jquery', 'jquery.someplguin'], function($) {
  // ...
});

新しい2.0ではshim configと呼ばれる機構が備わったため、プラグインのコードに手を加えることなく依存関係を明示できます。これに伴いorderプラグインが廃止になっています。

requirejs.config({
  shim: {
    'jquery.someplugin': ['jquery'] // somepluginはjqueryに依存しますよ、という宣言
  }
});
define('jquery', 'jquery.someplguin'], function($) {
  // ...
});

なおWEB+DB PRESSに解説が載ったというサードパーティライブラリのモジュール化が本機能に当たると思います(未確認)ので、より詳細な日本語資料をご覧になりたい方はこちらを購入されるといいのではと思います。

WEB+DB PRESS Vol.69

WEB+DB PRESS Vol.69

  • 作者: 大塚弘記,渡辺修司,堤智代,森田創,中島聡,A-Listers,はまちや2,川添貴生,井上誠一郎,近藤宇智朗,ヒノケン,後藤秀宣,佐藤鉄平,mala,奥野幹也,伊藤智章,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2012/06/23
  • メディア: 大型本
  • 購入: 12人 クリック: 138回
  • この商品を含むブログ (17件) を見る

フォールバック

HTML5 Boilerplateを読んだことがある方は、以下のコードをご存知でしょう。

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.7.2.min.js"><\/script>')</script>

まずはGoogleのCDNを読みに行って、失敗した時だけ自分自身がホストするスクリプトを使用するというものです。高速化のためにCDNを使いたい、でもCDNにトラブルがあった時のことも考えておきたい、という商用サイトならかならず持っているであろうニーズを満たすためのコードと言えます。


これを実現するコードは公式Wikiによると以下のとおりです。IE対応のためにenforceDefineオプションを指定しつつ、pathsオプションで候補となるファイルのパスを指定しています。

// quoted from official wiki.
// see https://github.com/jrburke/requirejs/wiki/Upgrading-to-RequireJS-2.0#wiki-pathsfallbacks

requirejs.config({
    //To get timely, correct error triggers in IE, force a define/shim exports check.
    enforceDefine: true,
    paths: {
        jquery: [
            'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min',
            //If the CDN location fails, load from this location
            'lib/jquery'
        ]
    }
});

//Later
require(['jquery'], function ($) {
});

複数バージョンの混在

新しいjQueryを使いたいのに、依存しているプラグインが新しいjQueryに対応していない!という状況に役立ちそうな機能です。同じrequire(['module'], ... )というコードでも全く異なるバージョンが解決されますので、モジュールごとに使用するバージョンを管理できます。

// quoted from official wiki.
// see https://github.com/jrburke/requirejs/wiki/Upgrading-to-RequireJS-2.0#wiki-mapconfig

requirejs.config({
    map: {
        '*': {
            'foo': 'foo1.2'
        },
        'some/oldmodule': {
            'foo': 'foo1.0'
        }
    }
});

この場合some/oldmoduleからはfooのバージョン1.0が、それ以外のモジュールからはバージョン1.2が使われることになります。