去年下半年开始,团队内部开始使用RequireJS作为模块加载器,并且建立了对应的模块化展现和开发平台。 前几天有个同事问我,使用RequireJS来加载一个CDN上的JS文件,没有得到预期的效果。代码大致如下:
require(["http://s7.qhimg.com/!b964179a/widget.1.0.2.js"], function(){
//logic code
})
查看了下对应的network,发现请求的URL并不是http://s7.qhimg.com/!b964179a/widget.1.0.2.js
,而是变成了http://s7.qhimg.com/?r=1397038555354
。这样返回的内容并不是一个JS,而是HTML,导致有脚本错误。
仔细查看了下URL,发现除了!这个特殊字符外,没有什么可疑的地方。拿着!去RequireJS的源码里查找,发现了如下的代码:
//Turns a plugin!resource to [plugin, resource]
//with the plugin being undefined if the name
//did not have a plugin prefix.
function splitPrefix(name) {
var prefix,
index = name ? name.indexOf("!") : -1;
if (index > -1) {
prefix = name.substring(0, index);
name = name.substring(index + 1, name.length);
}
return [prefix, name];
}
原来RequireJS里的插件机制使用了!作为分隔符,由于URL里含有!,导致URL被分割成2部分,最终请求的URL并不是我们预期的URL。
当时由于时间有限,让同事临时换了个URL,今天仔细看了下RequireJS的插件机制。
RequireJ核心只是个加载器,通过动态创建script标签来加载模块化的JS文件。但项目开发中,仅仅加载JS文件有时候并不能满足我们的需求,如:加载一个HTML片段,DomReady后执行,国际化语言包处理等等。
为了解决这些问题,RequireJS提供了插件的机制,插件和要加载的模块之间使用!分割。如:
require(["foo!something/for/foo"], function (something) {
//something is a reference to the resource
//"something/for/foo" that was loaded by foo.js.
});
这里的foo
是个插件,somthing/for/foo
是个模块。RequireJS会优先加载foo
这个插件对应的JS文件,然后插件里根据自己的逻辑处理something/for/foo
模块。
RequireJS官方默认提供了一些插件,如:text,domReady,i18n。
这里通过text插件大致介绍下插件的使用方法。
text插件可以用来加载一个非JS文件的内容,如:HTML片段,CSS片段。 可以从http://requirejs.org/docs/download.html#text下载text插件,可以放到RequireJS的plugins目录下。
那么就可以通过下面的方式来使用:
require(["module/require/2.1.8/plugins/text.js!html/a.html"], function(content){
console.log(content)
})
其中module和html是平行的目录,并且是配置baseUrl的目录下。 这样通过text插件就可以拿到html/a.html
的内容了,实际上text插件是通过ajax去获取内容的。
既然RequireJS使用了!作为插件的分隔符,那URL中就不能含有!了。
ps: URL含有!本身感觉也挺奇怪的。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8