从 RequireJS 到 SeaJS(4)
理解了 ID 规则,再来看 RequireJS API 文档 就轻松多了。
模块书写格式
作为模块加载器,需要明确模块应该怎样写,这就是模块书写格式(Module Authoring Format)。
对于文件加载器来说,约定非常少,比如 LABjs 只约定文件里不能有 document.write 等语句。
RequireJS 遵守的是 AMD 规范,SeaJS 遵守的是 Simple Wrappings 规范。
从表面上看,AMD 规范和 Wrappings 规范最大的不同是 factory 函数的参数不一样:
// 两者的基本格式都是: define(id?, denpendencies?, factory); // 在 AMD 中,factory 的参数由 dependencies 指定: define(['a'], function(a) { }); // 在 Wrappings 中,factory 的参数始终是 require, exports, module 三个: define(function(require, exports, module) { var a = require('a'); });
factory 的参数差异,直接导致 AMD 中的模块是立刻执行的,而 Wrappings 中的模块可以等到第一次 require 时才执行。这是当初 CommonJS 社区讨论最为激烈的争执点,彼此形成了不同的派系。理念上的差异,加上其他一些因素,最后直接导致 RequireJS 从 CommonJS 中脱离,自立门户成为了独立的社区。
理念上无对错。对于 SeaJS 来说,选择的是延迟执行,尽量与 CommonJS 以及 NodeJS 的模型保持一致。有兴趣的可以阅读我之前的博文:SeaJS 和 RequireJS 的异同
补充:每次想起这个话题,当初 CommonJS 社区的激烈讨论就历历在目。也正是因为理念上的差异,让我有了实现 SeaJS 的想法。当初 RequireJS 作者非常强势,虽然后来也支持了 Simplified CommonJS Wrapper, 但 CommonJS 原社区的不少人都不太认可 RequireJS 遵循的规范,并开始推出 BravoJS, FlyScript 等 loader, 可惜的是这些 loader 更新非常缓慢,目前 SeaJS 还算活跃的。
加载启动
对于安装了操作系统的计算机,最常用的启动方法是摁一下开机键。
对于浏览器,加载页面的普适方式是在地址栏上输入 url 并回车。
对于 NodeJS, 是在命令行中输入:
$ node xxx.js
所有这些都是“启动”。在 RequireJS 和 SeaJS 中,最便捷的启动是:
<script src="loader.js" data-main="main"></script>
RequireJS 可以通过全局 require 方法来启动:
require(['path/to/main.js']);
注意:作为启动用的 require, 参数必须是数组,即便只加载一个文件。这是 require 的陷阱之一,是由其设计导致的(在 RequireJS 里,require 还承担了获取模块接口的功能),这种不纯粹的设计是 SeaJS 不认可的。
SeaJS 里,普适的启动方式是:
seajs.use('path/to/main');
可以认为 seajs.use('xx')
就是 $ node xx
. 启动是和具体加载器相关的,启动之后,模块代码里就不必再出现加载器相关的东西了。比如 node 的模块代码里不会再出现 node. seajs 里,也不推荐在模块代码里出现 seajs (除了初始模块里可以用 seajs.config
进行配置)。
优化工具
RequireJS 的优化工具是 r.js
SeaJS 的是打包部署工具 spm
两者设计理念差异很大,在此就不比较了。