Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

模块标识 #258

Closed
lifesinger opened this issue Jul 6, 2012 · 12 comments
Closed

模块标识 #258

lifesinger opened this issue Jul 6, 2012 · 12 comments
Milestone

Comments

@lifesinger
Copy link
Member

模块标识

模块标识是一个字符串,用来标识模块。在 requirerequire.async 等加载函数中,第一个参数都是模块标识。

Sea.js 中的模块标识是 CommonJS 模块标识 的超集:

  1. 一个模块标识由斜线(/)分隔的多项组成。
  2. 每一项必须是小驼峰字符串、 ...
  3. 模块标识可以不包含文件后缀名,比如 .js
  4. 模块标识可以是 相对顶级 标识。如果第一项是 ...,则该模块标识是相对标识。
  5. 顶级标识根据模块系统的基础路径来解析。
  6. 相对标识相对 require 所在模块的路径来解析。

注意,符合上述规范的标识肯定是 Sea.js 的模块标识,但 Sea.js 能识别的模块标识不需要完全符合以上规范。 比如,除了大小写字母组成的小驼峰字符串,Sea.js 的模块标识字符串还可以包含下划线(_)和连字符(-), 甚至可以是 http://https://file:/// 等协议开头的绝对路径。

相对标识

相对标识以 . 开头,只出现在模块环境中(definefactory 方法里面)。相对标识永远相对当前模块的 URI 来解析:

// 在 http://example.com/js/a.js 的 factory 中:
require.resolve('./b');
  // => http://example.com/js/b.js

// 在 http://example.com/js/a.js 的 factory 中:
require.resolve('../c');
  // => http://example.com/c.js

顶级标识

顶级标识不以点(.)或斜线(/)开始, 会相对模块系统的基础路径(即 Sea.js 的 base 路径)来解析:

// 假设 base 路径是:http://example.com/assets/

// 在模块代码里:
require.resolve('gallery/jquery/1.9.1/jquery');
  // => http://example.com/assets/gallery/jquery/1.9.1/jquery.js

模块系统的基础路径即 base 的默认值,与 sea.js 的访问路径相关:

如果 sea.js 的访问路径是:
  http://example.com/assets/sea.js

则 base 路径为:
  http://example.com/assets/

sea.js 的访问路径中含有版本号时,base 不会包含 seajs/x.y.z 字串。 当 sea.js 有多个版本时,这样会很方便。

如果 sea.js 的路径是:
  http://example.com/assets/seajs/1.0.0/sea.js

则 base 路径是:
  http://example.com/assets/

当然,也可以手工配置 base 路径:

seajs.config({
  base: 'http://code.jquery.com/'
});

// 在模块代码里:
require.resolve('jquery');
  // => http://code.jquery.com/jquery.js

普通路径

除了相对和顶级标识之外的标识都是普通路径。普通路径的解析规则,和 HTML 代码中的 <script src="..."></script> 一样,会相对当前页面解析。

// 假设当前页面是 http://example.com/path/to/page/index.html

// 绝对路径是普通路径:
require.resolve('http://cdn.com/js/a');
  // => http://cdn.com/js/a.js

// 根路径是普通路径:
require.resolve('/js/b');
  // => http://example.com/js/b.js

// use 中的相对路径始终是普通路径:
seajs.use('./c');
  // => 加载的是 http://example.com/path/to/page/c.js

seajs.use('../d');
  // => 加载的是 http://example.com/path/to/d.js

提示

  1. 顶级标识始终相对 base 基础路径解析。
  2. 绝对路径和根路径始终相对当前页面解析。
  3. requirerequire.async 中的相对路径相对当前模块路径来解析。
  4. seajs.use 中的相对路径始终相对当前页面来解析。

文件后缀的自动添加规则

Sea.js 在解析模块标识时, 除非在路径中有问号(?)或最后一个字符是井号(#),否则都会自动添加 JS 扩展名(.js)。如果不想自动添加扩展名,可以在路径末尾加上井号(#)。

// ".js" 后缀可以省略:
require.resolve('http://example.com/js/a');
require.resolve('http://example.com/js/a.js');
  // => http://example.com/js/a.js

// ".css" 后缀不可省略:
require.resolve('http://example.com/css/a.css');
  // => http://example.com/css/a.css

// 当路径中有问号("?")时,不会自动添加后缀:
require.resolve('http://example.com/js/a.json?callback=define');
  // => http://example.com/js/a.json?callback=define

// 当路径以井号("#")结尾时,不会自动添加后缀,且在解析时,会自动去掉井号:
require.resolve('http://example.com/js/a.json#');
  // => http://example.com/js/a.json

设计原则

模块标识的规则就上面这些,设计的核心出发点是:

  1. 关注度分离。比如书写模块 a.js 时,如果需要引用 b.js,则只需要知道 b.js 相对 a.js 的相对路径即可,无需关注其他。
  2. 尽量与浏览器的解析规则一致。比如根路径(/xx/zz)、绝对路径、以及传给 use 方法的非顶级标识,都是相对所在页面的 URL 进行解析。

一旦理解了以上两点,一切都会很自然、很简单。不必刻意去记这些规则,多写写,自然就会。

@lifesinger
Copy link
Member Author

有任何问题,欢迎留言交流。
注意:已解决的问题,会在整理后删除掉。

This was referenced Mar 5, 2013
@peichao01
Copy link

关于手动指定ID和依赖,或者后期自动化构建为transport结构,都需要更为清晰的了解ID的解析模式,这里的介绍还没有面面俱到。这篇文章算是一个补充吧:seajs中模块ID注意事项,模块定义、模块加载、模块依赖的ID路径解析规则

@lifesinger
Copy link
Member Author

@peichao01 非常感谢补充,很详尽的说明。

@saraOrg
Copy link

saraOrg commented May 21, 2014

nice!

@ghost
Copy link

ghost commented Oct 10, 2014

在“自动添加规则”这一部分,
require.resolve('http://example.com/css/a.css');
的结果不应该是:
http://example.com/css/a.css.js吗?

@lianghrx
Copy link

路径解析中的paths参数

  1. paths在这里的仅仅能够识别顶级标示, 相对于base路径的普通路径均不能被正确识别, 也就是paths仅支持base路径下的路径扩展;
  2. 是否能够使paths支持相对于base路径的普通路径解析(或者仅支持相对标示), 这样可以支持base路径外的路径扩展, 有利于统一模板路径配置, 不必再设置独立的相对路径, 所有路径都可以根据base路径进行配置;

@afc163 afc163 mentioned this issue Mar 3, 2015
@Sessionking
Copy link

seajs.use 中的相对路径始终相对当前页面来解析。 应该是相对于sea.js的地址吧,

@liujie2019
Copy link

学习了,非常感谢

@Timi-code
Copy link

在引入css文件的时候,貌似必须添加后缀的吧。在script里面引入css的时候就回找不到,在define里面引入css 的时候会自动添加上.js的后缀引入导致找不到。

@baiduoduo
Copy link

同问,在“自动添加规则”这一部分,
require.resolve('http://example.com/css/a.css');
的结果不应该是:
http://example.com/css/a.css.js吗?

@sxmsxmsxm
Copy link

感谢分享

@chinleo
Copy link

chinleo commented Mar 17, 2017

总结下:
./开头:本级路径
../开头:上级
/开头:域名之后的根路径
名称开头:相对于base的路径

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants