04月09, 2014

URL中的!和RequireJS的插件机制

去年下半年开始,团队内部开始使用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。

RequireJS里的插件机制

当时由于时间有限,让同事临时换了个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.js文件在module/require/2.1.8/require.js
  • text.js文件在module/requirejs/2.1.8/plugins/text.js

那么就可以通过下面的方式来使用:

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含有!本身感觉也挺奇怪的。

本文链接:http://welefen.com/post/!-in-url-and-requirejs-plugins.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。