岁月如歌

用开放的心态,打造专业的人生。

从 RequireJS 到 SeaJS(3)

with 2 comments

来看 RequireJS 的 API 页面:api.html, 该篇博客着重分析 RequireJS 和 SeaJS 在 ID 规则上的异同。

RequireJS 的 ID 规则

对于模块加载器来说,模块 id 遵守的规则非常重要。

首先来定义几个概念。假设当前页面路径为 http://t.com/a/b/c.html, 则:

  1. pageRoot = http://t.com
  2. pageUrl = http://t.com/a/b
  3. baseUrl: 在 RequireJS 里,默认情况下,baseUrl 就是 pageUrl, 除非:
    • 通过 require.config 更改了 baseUrl
    • 指定了 data-main, 比如
      <script src="require.js" data-main="scripts/main"></script> 
      

      这时 baseUrl 为 pageUrl/scripts

  4. paths: 表示路径的缩写,通过 config 来配置:
    require.config({ paths: { 'some': 'xxx/zzz' } })
    

    这时,some/a 实际上代表 xxx/zzz/a

  5. moduleUrl: 如果模块路径为 http://t.com/path/to/a.js, 则 moduleUrl = http://t.com/path/to

RequireJS 的 id 规则为:首先,会通过 paths 解析,解析完成后:

  1. Page ID
    • .js 结尾的,比如 some/a/b.js
    • / 开头的,比如 /a/b
    • http(s):// 开头的

    Page ID 的解析规则与 script src="xxx" 中的 xxx 一样。

  2. some/module 这种 Top-Level ID, 会解析成 baseUrl/some/module.js
  3. ./some/module 这种 Relative ID, 会解析成 moduleUrl/some/module.js

SeaJS 的 ID 规则

文档:module-identifier.html

SeaJS 的 ID 规则可以总结为:

  1. 省略约定.js 后缀可以省略。 require('path/to/a.js')require('path/to/a') 是一样的。
  2. 环境相关: 除了 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 可以分成两类:

  1. Top-Level ID: some/module 这种,会根据 baseUrl 来定位。
  2. Context ID: 除了 some/module 之外的所有形式,会根据当前环境来定位。

ID 规则对使用体验的影响

RequireJS 里有 Page ID 的概念,和浏览器解析 src 的规则保持一致。
SeaJS 里则有省缺 .js 后缀的约定,和 CommonJS 以及 NodeJS 的约定保持一致。

这个取舍,使得 RequireJS 的 ID 更接近文件路径,SeaJS 的 ID 则更接近模块标识。
这其实是由两者的定位决定的:RequireJS 想同时是文件和模块加载器,SeaJS 则只专注于模块加载器。

当采用 Simplified CommonJS Wrapper 格式时,RequireJS 和 SeaJS 的解析规则基本一致:

// xxx/to/a.js
define(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 尽量保持一致。

Advertisements

Written by lifesinger

October 30, 2011 at 16:11

Posted in Articles

2 Responses

Subscribe to comments with RSS.

  1. […] ID 规则,再来看 RequireJS API 文档 […]

  2. […] 从 RequireJS 到 SeaJS(3) […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s