我开发了一个JavaScript插件,该插件将包含在我们客户的网站中。我创建的插件依赖于一些外部库,这些库作为一个大包捆绑并交付给客户端:jQuery 1.8.2和KnockoutJS v3.0.0。
该插件可以在大多数站点上正常运行,但是如果宿主站点使用RequireJS,则我的包无法加载,因为KnockoutJS自动检测到RequireJS存在并尝试使用它。这是引发的错误:
Mismatched anonymous define() module
显然,我在RequireJS网站上找到了错误消息的“解释”。不幸的是,我不知道如何避免这种情况。在我的KnockoutJS库的本地副本中,我发现了令人反感的行:
(function(factory) {
// Support three module loading scenarios
if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
// [1] CommonJS/Node.js
var target = module['exports'] || exports; // module.exports is for Node.js
factory(target);
} else if (typeof define === 'function' && define['amd']) {
// [2] AMD anonymous module
define(['exports'], factory);
} else {
// [3] No module loader (plain <script> tag) - put directly in global namespace
factory(window['ko'] = {});
}
}
如果我手动编辑此文件,以使条件[2]从不执行而仅条件[3]每个都执行,则一切正常。当然,我不想这样做,因为它需要我编辑一个外部库,我希望它保持原始状态,以便以后进行升级。
我感觉可能有一种方法可以使这项工作生效,我只是不了解RequireJS是如何工作的。显然,KnockoutJS尝试与RequireJS配合使用,但是就我而言,这是失败的。对我而言,在这种情况下,即使RequireJS存在,我也不需要KnockoutJS来使用它。
如何使这两个库并排工作?
编辑
我无法控制何时加载我的库与宿主站点已加载的所有其他库。实际上,大多数时候我的插件都将包含在内,它是由没有Web开发经验的人使用可怕的WYSIWYG平台(例如WordPress,Webs.com或Weebly)来完成的,因此有时我的脚本标签可能会成为顶峰元素,有时它可能包含在body元素中的某个位置。
另外,要明确一点,我的库不使用RequireJS。碰巧的是,一个尝试使用我的库的客户确实使用RequireJS,并且当包含我的库时,KnockoutJS(与我的库捆绑在一起,但尚未在宿主站点上)引发异常,因为它认为需要向RequireJS注册自己(或者至少是我对异常的猜测)。
虽然原则上我不反对加载我的代码依赖于需求的库,但事实是,这将给我的用户带来缓慢而糟糕的体验,因为它将花费额外的请求/响应周期来加载它们。
好吧,最简单的方法可能是在requirejs之前加载剔除。ko将不再检测到存在需求,并将与选项[3]一起使用。如果您无法执行此操作,则另一种选择是将插件和ko文件添加到require层次结构中。
因此,假设您的插件如下所示:
(function(ko){
//stuff
ko.applyBindings({});
})(ko)
您需要将其更改为:
require([
"knockout-3.0.0.js" // this should be the url you use for knockout
], function(ko){
//stuff
ko.applyBindings({});
})
而不是将kickout.js文件作为单独的标签加载。需要处理加载。服务器当然仍然必须能够传递“ knockout-3.0.0.js” URL。这就是需求的工作方式。它会将您作为元素传递的所有url加载到require的数组参数中,并将它们作为参数返回的内容传递给函数。
如果您需要将插件文件和ko文件都缩小/捆绑到一个文件中,则可以使用reuquirejs缩小器/优化器(http://requirejs.org/docs/optimization.html)。它将导航依赖关系树,并且仅输出一个js文件,其中包含所有模块。这里有一个怪癖:您需要删除.js扩展名以使Minifier起作用,请阅读有关该文档的更多信息,我刚才提到它是为了省去一些麻烦。
另外,可以在以下位置找到有关如何与require一起使用ko的更多文档:http : //knockoutjs.com/documentation/amd-loading.html
在操作编辑后进行编辑:
好的,因此在这种情况下,您应该创建一个单独的范围,您可以在其中执行所需的操作。您需要将ko代码复制到文件中,但是这样,您至少会得到一个文件。
因此,首先创建一个范围:
(function(){
})()
然后在其中复制ko代码:
(function(){
//ko code here, should be a single, minified line
})()
然后,您需要诱使ko使用选项3,因此请执行以下操作:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
})()
(可选)如果您不希望整个页面都可以使用ko,则可能还需要在上述步骤中重新分配窗口。
现在添加您的插件代码:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
//plugin code here;
})()
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句