Javascript 使用不带导出的UMD来简单地增加依赖性是否合理?
我正在创建我的第一个AngularJS模块,用于开源发行版。我想用一种便于他人消费的方式来包装它 UMD项目为导出与AMD、CommonJS(或至少是Node)和浏览器全局兼容的JavaScript模块提供了一个解决方案:Javascript 使用不带导出的UMD来简单地增加依赖性是否合理?,javascript,angularjs,amd,commonjs,umd,Javascript,Angularjs,Amd,Commonjs,Umd,我正在创建我的第一个AngularJS模块,用于开源发行版。我想用一种便于他人消费的方式来包装它 UMD项目为导出与AMD、CommonJS(或至少是Node)和浏览器全局兼容的JavaScript模块提供了一个解决方案: (function (root, factory) { if (typeof define === 'function' && define.amd) { define(['b'], factory); // AMD } else if (ty
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['b'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('b')); // Node
} else {
root.returnExports = factory(root.b); // browser global (root is window)
}
}(this, function (b) {
// use b in some fashion
return {}; // return a value to define the module export
}));
但是,由于AngularJS有自己的内部模块系统,注册模块只需在angular
对象上调用一个方法即可,即angular.module()
。因此,UMD模块不需要导出任何内容;它只需要在angular
上进行操作。在前面的例子中,我认为应该是这样的:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
factory(require(['b'])); // AMD
} else if (typeof exports === 'object') {
factory(require('b')); // Node
} else {
factory(root.b); // browser global (root is window)
}
}(this, function (b) {
// use b in some fashion
}));
或者,针对我的情况:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
factory(require(['angular'])); // AMD
} else if (typeof exports === 'object') {
factory(require('angular')); // Node
} else {
factory(root.angular); // browser global (root is window)
}
}(this, function (angular) {
angular.module( ... );
}));
这没什么大不了的,还是违背了UMD的精神?我这样问是因为我找不到任何不导出任何内容的UMD模式。作为angular插件,最好提供一个导出生成器的模块,这样人们就可以对“angular意味着什么”负责。例如,假设我正在使用angular的定制调试版本,但想使用您的代码:现在,我不能,因为您已经决定为我要求angular。这似乎是个好主意,但事实并非如此:
var myangular = require('debug-angular/ext/symbolised');
var yourmodule = require('yourmodule');
yourmodule.register(myangular);
现在我知道,作为开发人员,您的代码将使用我的angular,而不是现在加载两个不同版本的angular,以及由此产生的所有有趣的版本不匹配错误
因此,更好的umd工厂应该是:
(function (root, factory) {
if (typeof define !== 'undefined' && define.amd) {
define(['angular'] , function (angular) {
factory(angular);
});
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = {
register: function(angular) {
factory(angular);
}
};
} else {
factory(root.angular); // browser global (root is window)
}
}(this, function (angular) {
angular.module( ... );
}));
我看不出使用这种模式有什么错。正如您可能已经发现的,Angular在现有模块系统中使用的不是很好,因为它使用自己的模块系统,但是模块不必导出任何东西。项目的主模块多久导出一次?通常,它只是得到依赖项 如果您正在寻找一个类似的例子,那么可以看看jQuery mousewheel插件,它使用UMD,但依赖于jQuery 摘自
jquery.mouseweel.js
:
(function (factory) {
if ( typeof define === 'function' && define.amd ) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports = factory;
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
一个区别是,它为Node/CommonJS导出返回一个构造函数,这样您就可以传入希望扩展的jQuery对象
另一方面,您的UMD实现有一个问题,在AMD部分 你有:
factory(require(['b'])); // AMD
如果您需要:
define(['b'], factory); // AMD
由于AMD是异步的,您将无法同步地需要角度模块
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['b'], factory); // AMD
} else if (typeof exports === 'object') {
factory(require('b')); // Node
} else {
factory(root.b); // browser global (root is window)
}
}(this, function (b) {
// use b in some fashion
}));
我认为通常由构建工具来决定要包含哪个版本的库(调试还是压缩)。另外,如果他是在开发angular库,那么假设并要求angular而不是其他人的库是非常合理的。只要我的两分钱。我不是在说“缩小还是不缩小”,想想jquery和zepto:完全不同的库,但99%的API是相同的,所以几乎任何依赖jquery的插件都可以与zepto配合使用。。。只要它不盲目加载自己的jquery。我可以有一个与angular具有相同API的库,在这种情况下,模块“有益地”加载angular对我来说将是有用的相反。在这种情况下,我认为正确的实现将是一个接口,第三方库将实现该接口以提供一致的API。但这一切都是毫无意义的,因为@Bungle表示他想编写一个有角度的JS模块。因此,他不应该支持另一个图书馆,如果他不想-特别是因为角度是他的模块正在建立的基础,可以说是角Web应用的基础。但是,如果我们谈论的是日期,我会100%同意你的看法。jquery.mouseweel.js就是一个很好的例子,看起来非常有效,谢谢。@alexanderomara您应该将代码片段更改为正确的内容,而不是将其复制到OP的原始版本中,这样粗心的读者就不会只是将代码片段复制粘贴到您的文档中post@I-林果接球不错!复制粘贴失败。