我正在为我开发的javascript库添加AMD支持。
这个库可能使用jquery但是如果没有加载jquery它仍然可以工作。
在定义模块依赖项时,有一种方法可以将依赖项设置为“可选”,这样如果缺少该库,模块仍然可以工作吗?
答案 0 :(得分:26)
我最近遇到了完全相同的问题,这就是我修复它的方法。我定义了一个名为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模块,传递给回调函数的参数将是一个空对象。
答案 1 :(得分:12)
您无法将其设置为可选,但您可以使用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);
...
}
});
完整示例here。
答案 2 :(得分:-1)
此处不需要插件。
这可以在没有RequireJS插件的情况下完成。此外,您也可以为UMD模块执行此操作。
实际上非常简单,使用require.defined
,它可以让您测试模块是否已经加载。如果是这样,你require
jQuery并使用它,否则你只需跳过可选部分:
define(['require'], function(require){
if (require.defined('jquery') {
var $ = require('jquery');
$.fn.something = function(){};
}
});
注意我们如何添加'require'
作为依赖项,因此我们得到一个本地require函数,其上有defined
方法。
另请注意,如果jQuery已在此模块之前加载,则此代码将仅查找jQuery。如果某个模块在之后加载了jQuery ,那么这个模块已经加载了,那么之后它就不会获取jQuery。
这不会尝试加载jQuery,因此不会在日志中导致错误消息。
如果您希望您的库支持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 - check if module is installed without actually requiring it https://github.com/jrburke/requirejs/issues/856