Подтвердить что ты не робот

RequireJS необязательная зависимость

Я добавляю поддержку AMD в библиотеку javascript, которую я разрабатываю.

Эта библиотека может использовать jquery, но она будет работать, если jquery не загружен.

При определении зависимости модуля есть способ установить зависимость как "необязательный", так что если эта библиотека отсутствует, модуль все равно будет работать?

4b9b3361

Ответ 1

У меня была точно такая же проблема в последнее время, и вот как я ее исправил. Я определил плагин RequireJS с именем optional, который игнорирует модули, которые не могут загружаться, явно определяя их как пустой объект (но я полагаю, вы могли бы также определить его как нуль или что-нибудь еще, если бы захотели).

Вот код (протестирован с 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 не может быть загружен, параметр, переданный вашей функции обратного вызова, будет пустым.

Ответ 2

Вы не можете установить его дополнительно, но вы можете поймать ошибку и выгрузить модуль, используя 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);
        ...
     }
});

Полный пример здесь.

Ответ 3

Плагин для этого не нужен.

Это можно сделать без плагинов для RequireJS. Кроме того, вы можете сделать это и для модулей UMD.

Использование jQuery только при его загрузке

Это на самом деле довольно просто, используя require.defined, который позволяет проверить, загружен ли модуль или нет. Если это так, вы require jQuery и используйте его, иначе вы просто пропустите необязательную часть:

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

Обратите внимание, как мы добавляем 'require' в качестве зависимости, поэтому мы получаем локальную требуемую функцию, которая имеет на ней метод defined.

Также обратите внимание, что этот код найдет только jQuery, если он был загружен до этого модуля. Если какой-либо модуль загружает jQuery после того, как этот модуль уже загружен, он не будет записывать jQuery впоследствии.

Это не будет пытаться загрузить jQuery и, следовательно, не вызовет сообщение об ошибке в журналах.

Бонус: поддержка UMD

Если вы хотите, чтобы ваша библиотека поддерживала загрузчики AMD (RequireJS), CommonJS (Node) и обычные теги script и имела необязательную зависимость от 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 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