web-dev-qa-db-ja.com

RequireJSでshim configを使用する理由とタイミング

ここからrequirejsドキュメントを読みます api

requirejs.config({
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Using a function allows you to call noConflict for
                //libraries that support it, and do other cleanup.
                //However, plugins for those libraries may still want
                //a global. "this" for the function will be the global
                //object. The dependencies will be passed in as
                //function arguments. If this function returns a value,
                //then that value is used as the module export value
                //instead of the object found via the 'exports' string.
                return this.Foo.noConflict();
            }
        }
    }
});

しかし、私はそれの一部を取得していませんshimシムを使用する理由と設定方法を教えてください。

シムを使用する理由とタイミングを例を挙げて説明してください。ありがとう。

96
Anil Gupta

Shimの主な用途は、AMDをサポートしないライブラリで使用することですが、それらの依存関係を管理する必要があります。たとえば、上記のバックボーンとアンダースコアの例では、バックボーンにはアンダースコアが必要であることがわかっているため、次のようなコードを記述したとします。

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequireJSは、UnderscoreとBackboneの両方の非同期リクエストを開始しますが、あなたはどちらが最初に戻るかわからないので、Backboneがロードされる前にUnderscoreで何かをしようとする可能性があります。

注:このアンダースコア/バックボーンの例は、両方のライブラリがAMDをサポートする前に書かれました。しかし、AMDをサポートしていない現在のライブラリには、この原則が当てはまります。

「init」フックを使用すると、他の高度な処理を実行できます。ライブラリが通常2つの異なるものをグローバル名前空間にエクスポートするが、それらを単一の名前空間の下で再定義する場合。または、ロードしているライブラリのメソッドにサルのパッチを適用することもできます。

より多くの背景:

109
explunit

RequireJS APIドキュメントに従って、shimは

Define()を使用せずに依存関係を宣言し、モジュール値を設定する、従来の「ブラウザグローバル」スクリプトの依存関係、エクスポート、およびカスタム初期化を構成します。

-依存関係の設定

2つのjavascriptモジュール(moduleAとmoduleB)があり、そのうちの1つ(moduleA)がもう一方(moduleB)に依存しているとします。これらは両方とも独自のモジュールに必要なので、require()またはdefine()で依存関係を指定します

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

ただし、require自体はAMDに従うため、どちらを早く取得するかはわかりません。これがシムが救助に来る場所です。

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

これにより、moduleAがロードされる前にmoduleBが常にフェッチされます。

-エクスポートの設定

Shimエクスポートは、RequireJSに、グローバルオブジェクト(もちろん、ブラウザを使用している場合はウィンドウ)のどのメンバーが実際のモジュール値であるかを伝えます。 moduleAがwindowにそれ自体を 'modA'として追加するとしましょう(jQueryとアンダースコアがそれぞれ$と_として行うように)、エクスポート値を 'modA'にします。

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

RequireJSにこのモジュールへのローカル参照を提供します。グローバルmodAも引き続きページに存在します。

-古い「ブラウザグローバル」スクリプトのカスタム初期化

これはおそらく、shim configの最も重要な機能であり、独自のモジュールの依存関係として「ブラウザグローバル」、「非AMD」スクリプト(モジュールパターンにも従わない)を追加できます。

ModuleBがfuncA()とfuncB()の2つの関数だけを備えた単純な古いjavascriptだとしましょう。

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

これらの関数は両方ともウィンドウスコープで使用できますが、RequireJSでは、混乱を避けるためにグローバル識別子/ハンドルを使用することをお勧めします。そのため、シムを次のように構成します

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

Init関数からの戻り値は、「exports」文字列を介して見つかったオブジェクトの代わりに、モジュールのエクスポート値として使用されます。これにより、独自のモジュールでfuncBを次のように使用できます。

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

これが役に立てば幸いです。

63
nalinc