web-dev-qa-db-ja.com

requireJSオプションの依存関係

開発したjavascriptライブラリにAMDサポートを追加しています。

このライブラリはjqueryを使用する場合がありますが、jqueryがロードされていない場合でも機能します。

モジュールの依存関係を定義するときに、依存関係を「オプション」として設定する方法があります。これにより、そのライブラリが欠落している場合でも、モジュールは機能しますか?

27

最近、まったく同じ問題が発生しました。これを修正する方法を説明します。 optionalというRequireJSプラグインを定義しました。これは、モジュールを空のオブジェクトとして明示的に定義することにより、ロードに失敗したモジュールを無視します(ただし、必要に応じてnullなどとして定義することもできます)。

コードは次のとおりです(RequireJS 2.1.15でテスト済み)。

define("optional", [], {
    load : function (moduleName, parentRequire, onload, config){

        var onLoadSuccess = function(moduleInstance){
            // Module successfully loaded, call the onload callback so that
            // requirejs can work its internal magic.
            onload(moduleInstance);
        }

        var onLoadFailure = function(err){
            // optional module failed to load.
            var failedId = err.requireModules && err.requireModules[0];
            console.warn("Could not load optional module: " + failedId);

            // Undefine the module to cleanup internal stuff in requireJS
            requirejs.undef(failedId);

            // Now define the module instance as a simple empty object
            // (NOTE: you can return any other value you want here)
            define(failedId, [], function(){return {};});

            // Now require the module make sure that requireJS thinks 
            // that is it loaded. Since we've just defined it, requirejs 
            // will not attempt to download any more script files and
            // will just call the onLoadSuccess handler immediately
            parentRequire([failedId], onLoadSuccess);
        }

        parentRequire([moduleName], onLoadSuccess, onLoadFailure);
    }
});

次に、オプションで単純に使用してモジュールを要求できます。

require(['optional!jquery'], function(jquery){...});

jqueryモジュールをロードできなかった場合、コールバック関数に渡されるパラメーターは空のオブジェクトになることを知っています。

26
LordOfThePigs

実際にはオプションに設定することはできませんが、undefを使用してエラーをキャッチし、モジュールをアンロードできます。

require(['jquery'], function ($) {
    //Do something with $ here
}, function (err) {
    //The errback, error callback
    //The error has a list of modules that failed
    var failedId = err.requireModules && err.requireModules[0];
    if (failedId === 'jquery') {
        //undef is function only on the global requirejs object.
        //Use it to clear internal knowledge of jQuery. Any modules
        //that were dependent on jQuery and in the middle of loading
        //will not be loaded yet, they will wait until a valid jQuery
        //does load.
        requirejs.undef(failedId);
        ...
     }
});

完全な例 ここ

12
asgoth

これにはプラグインは必要ありません。

これは、RequireJSのプラグインなしで実行できます。さらに、UMDモジュールに対してもこれを行うことができます。

すでにロードされている場合にのみjQueryを使用する

require.definedを使用すると、実際には非常に簡単です。これにより、モジュールがすでにロードされているかどうかをテストできます。その場合は、require jQueryを使用して使用します。それ以外の場合は、オプションの部分をスキップします。

define(['require'], function(require){
  if (require.defined('jquery') {
    var $ = require('jquery');
    $.fn.something = function(){};
  }
});

依存関係として'require'を追加する方法に注目してください。これにより、definedメソッドを持つローカルのrequire関数が得られます。

また、このコードは、このモジュールの前にロードされている場合にのみjQueryを検出することに注意してください。一部のモジュールがjQueryafterをロードした場合、このモジュールはすでにロードされているため、後でjQueryを取得しません。

これはjQueryを読み込もうとしないため、ログにエラーメッセージが表示されることはありません。

ボーナス:UMDサポート

ライブラリでAMDローダー(RequireJS)、CommonJS(Node)、および通常のスクリプトタグをサポートする場合、およびにはオプションがありますjQueryへの依存、これがあなたができることです:

(function(u, m, d) {
    if ((typeof define == 'object') && (define.AMD)) {
        // handle AMD loaders such as RequireJS
        define(m, ['require'], d);
    }
    else if (typeof exports === 'object') {
        // handle CommonJS here... Does not really make sense for jQuery but
        // generally, you can check whether a dependency is already loaded
        // just like in RequireJS:
        var $ = null;
        try {
            require.resolve('jquery'));
            // the dependency is already loaded, so we can safely require it
            $ = require('jquery');
        } catch(noJquery) {}
        module.exports = d(null, $);
    }
    else {
        // regular script tags. $ will be available globally if it's loaded
        var $ = typeof jQuery == 'function' ? jQuery : null;
        u[m] = d(null, $);
    }
})(this, 'mymodule', function(require, $) {

    // if `$` is set, we have jQuery... if not, but `require` is set, we may
    // still get it here for AMD loaders
    if (!$ && require && require.defined && require.defined('jquery')) {
        $ = require('jquery');
    }

    // At this point, `$` either points to jQuery, or is null.
});

参考文献

Node.js-モジュールが実際に必要とせずにインストールされているかどうかを確認しますhttps://github.com/jrburke/requirejs/issues/856

0
Stijn de Witt