RequireJSでのライブラリの依存設定

RequireJSを使って以下のようにjQuery-UIを利用するコードを記述したところ、 JSエラーが出た。

define([
    '../bootstrap/bootstrap',
    '../jquery/ui/jquery-ui.custom',
    '../jquery/ui/jquery.ui.widget',
    '../jquery/ui/jquery.ui.mouse'
  ], function(){
      ....
    });
  });
Uncaught TypeError: Object function ( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context, rootjQuery );
  } has no method 'widget' jquery.ui.mouse.js:21

jquery.ui.mouse.jsをロードするタイミングで依存しているjquery.ui.widgetがロードされていないらしい。 Chromeのdeveloper-toolで見るとその時のロード順序は以下のようになっていた。

f:id:t_gaisho:20130317140549p:plain

jquery.ui.mouse.jsが先にロードされてしまっている。 ただこのロード順序は非同期のため、その時によってバラバラ。運がよければエラーにならなかったりする。。

依存するライブラリを必ず読み込んだ後にロードするようには以下のようにRequireJSのshim設定を定義する必要がある。

    <script>
    var require = {
      shim: {
        '../jquery/ui/jquery.ui.mouse' : {
          deps: [ '../ui/jquery-ui.custom', '../ui/jquery.ui.widget' ]
        }
      }
    };
    </script>

depsの所でjquery.ui.mouseはjquery-ui.customとjquery.ui.widgetに依存しているという情報を定義している。

更にdefine関数の呼び出し箇所で依存しているファイルの記述を削除。shim設定しているため自動で読み込んでくれる。

define([
    '../bootstrap/bootstrap',
    '../jquery/ui/jquery.ui.mouse'
  ], function(){
    ...
  });

この状態で画面のロードを行うとjsエラーは発生しなくなった。

f:id:t_gaisho:20130317141256p:plain

'../ui/jquery-ui.custom', '../ui/jquery.ui.widget' が '../jquery/ui/jquery.ui.mouse' よりも先にロードされている。常に。