Web端JavaScript模块化并不是横空出世,凭空捏造的,目前的这些SeaJS,RequireJS,AMD以及CMD标准是怎么形成的呢?
感觉dojo是比较早模块化的,然后yui3也开始模块化了。标准都是晚于这些探索者,而SeaJS和RequireJS则是提供了基于某些标准的实现。标准被广泛接受之后,又影响到dojo之类的框架。 我最早接触到的模块化解决方案是国内的JSI,比以上所有这些都要更早。
@imzshh @aa272121742 Web端JavaScript模块化并不是横空出世,凭空捏造的,目前的这些SeaJS,RequireJS,AMD以及CMD标准是怎么形成的呢?
据我所知,Web端的模块化并不是一开始就有的。泛泛地讲,jQuery其实也是一个模块,通过全局与其他模块(业务模块)通信;
Dojo是一个比较重的库,Dojo的开发者开发Loader来加载和组织Dojo的脚本;但初期的Dojo Loader是采用同步的XHR加载的,不能加载不同域下的模块,且性能不行;Loader的主要贡献者James Burke开发了Dojo XD Loader,采用script标签的方式,可以加载其他域下的模块。由于Dojo的历史原因和Dojo模块的复杂性(国际化)James开始开发一个叫做RunJS的独立模块加载器;
其实同时代还有其他一些脚本加载器,比如LABjs,Twitter都在使用,它以并行加载高性能为优。模块化加载并不是一开始就有的,最开始,更多的是脚本加载器。
James在开发RunJS的同时,CommonJS标准制定出来,且由NodeJS加以实现。当然NodeJS的模块无法直接在浏览器中使用(require()),于是James在CommonJS社区中给出了自己Web端的模块定义提案(其实同时其他人也给出了提案,而且我觉得不比他的查),主要就是从Dojo Loader中借用过来的,RunJS实现的接口。再不断交流和摸索过程中,逐渐形成了AMD规范,James把RunJS更名为了RequireJS,继续实现并支持AMD。但AMD并不是完美无缺的。
SeaJS是淘宝的玉伯开发的,我想是脱胎于Kissy,而在KIssy之前,淘宝是在使用YUI的,YUI3实现了seed模式的模块加载器,很多东西来自于Dojo。
虽然看到过JSI一些相关的信息,但具体就不太清楚了,有没有相关的文档?
@logicthink 这个问题稍稍有点复杂。不过可以看这里:https://github.com/jashkenas/coffee-script/blob/master/Cakefile#LC97。
首先,CoffeeScript的源码是Node.js,即有require exports什么的,那怎么把这些代码包裹起来在客户端使用呢,下面是CoffeeScript的方法,给浏览器用到coffee-script.js的整体结构:
(function (root) {
var CoffeeScript = function () {
function require(path) {
return require[path];
}
require['./helpers'] = new function () {
var exports = this;
(function () {
var extend, flatten, _ref;
exports.starts = function (string, literal, start) {
return literal === string.substr(start, literal.length);
}
}).call(this);
};
/* ..... */
/* require ['./coffee-script'] = new function(){} */
/* ..... */
return require['./coffee-script'];
}();
if (typeof define === 'function' && define.amd) {
define(function () {
return CoffeeScript;
});
} else {
root.CoffeeScript = CoffeeScript;
}
}(this))
它使用了型如:
require['./helpers'] = new function () {
var exports = this;
(function () {
//node code start
var extend, flatten, _ref;
exports.starts = function (string, literal, start) {
return literal === string.substr(start, literal.length);
}
//node code end
}).call(this);
};
把每一个node文件打包到了客户端。虽然有出现require这个关键字,但是并没有采用什么框架,而只是一个共享的命名空间,来在各个node文件之间共享,传递模块。
另外一方面:
if (typeof define === 'function' && define.amd) {
define(function () {
return CoffeeScript;
});
} else {
root.CoffeeScript = CoffeeScript;
}
这段代码就是让coffee-script.js兼容AMD模块标准,可以使用AMD加载器来加载。