从 RequireJS 到 SeaJS(3)
来看 RequireJS 的 API 页面:api.html, 该篇博客着重分析 RequireJS 和 SeaJS 在 ID 规则上的异同。
RequireJS 的 ID 规则
对于模块加载器来说,模块 id 遵守的规则非常重要。
首先来定义几个概念。假设当前页面路径为 http://t.com/a/b/c.html, 则:
- pageRoot =
http://t.com - pageUrl =
http://t.com/a/b - baseUrl: 在 RequireJS 里,默认情况下,baseUrl 就是 pageUrl, 除非:
- 通过 require.config 更改了 baseUrl
- 指定了 data-main, 比如
<script src="require.js" data-main="scripts/main"></script>
这时 baseUrl 为
pageUrl/scripts
- paths: 表示路径的缩写,通过 config 来配置:
require.config({ paths: { 'some': 'xxx/zzz' } })这时,
some/a实际上代表xxx/zzz/a - moduleUrl: 如果模块路径为
http://t.com/path/to/a.js, 则 moduleUrl =http://t.com/path/to
RequireJS 的 id 规则为:首先,会通过 paths 解析,解析完成后:
- 是 Page ID:
- 以
.js结尾的,比如some/a/b.js - 以
/开头的,比如/a/b - 以
http(s)://开头的
Page ID 的解析规则与
script src="xxx"中的 xxx 一样。 - 以
- 是
some/module这种 Top-Level ID, 会解析成baseUrl/some/module.js - 是
./some/module这种 Relative ID, 会解析成moduleUrl/some/module.js
SeaJS 的 ID 规则
SeaJS 的 ID 规则可以总结为:
- 省略约定:
.js 后缀可以省略。require('path/to/a.js')和require('path/to/a')是一样的。
- 环境相关: 除了 Top-Level ID 始终相对 baseUrl 来定位,其他 ID 都是相对当前环境来定位。
举例如下:
// 在 http://t.com/test.html 中:
seajs.use(['./a', 'b', 'c.js', '/d', 'http://x.com/e']);
// 会下载
// http://t.com/a.js
// baseUrl/b.js
// baseUrl/c.js
// http://t.com/d.js
// http://x.com/e.js
// 在 http://cdn.com/path/to/t.js 中:
define(function(require) {
require('./a');
require('b');
require('c.js');
require('/d');
require('http://x.com/e');
});
// 会下载
// http://cdn.com/path/to/a.js
// baseUrl/b.js
// baseUrl/c.js
// http://cdn.com/d.js
// http://x.com/e.js
可以看出,在 SeaJS 里,ID 可以分成两类:
- Top-Level ID:
some/module这种,会根据 baseUrl 来定位。 - Context ID: 除了
some/module之外的所有形式,会根据当前环境来定位。
ID 规则对使用体验的影响
RequireJS 里有 Page ID 的概念,和浏览器解析 src 的规则保持一致。
SeaJS 里则有省缺 .js 后缀的约定,和 CommonJS 以及 NodeJS 的约定保持一致。
这个取舍,使得 RequireJS 的 ID 更接近文件路径,SeaJS 的 ID 则更接近模块标识。
这其实是由两者的定位决定的:RequireJS 想同时是文件和模块加载器,SeaJS 则只专注于模块加载器。
当采用 Simplified CommonJS Wrapper 格式时,RequireJS 和 SeaJS 的解析规则基本一致:
|
1
2
3
4
5
6
|
// xxx/to/a.jsdefine(function(require, exports, module) { require('a'); // baseUrl/a.js require('./b'); // xxx/to/b.js require('./b.js'); // xxx/to/b.js}); |
RequireJS 的 ID 规则是比较容易让人混淆的,特别对于新手来说。有没有 .js 后缀,以及采用的模块书写格式,都会影响解析规则。
SeaJS 的 ID 规则更简单纯粹,和 CommonJS 以及 NodeJS 尽量保持一致。

浙公网安备 33010602011771号