-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
ID 和路径匹配原则 #930
Comments
有任何问题,欢迎留言交流。 |
顶 @afc163 倾情整理文档。大赞。 |
这篇文章就应该放到这里 http://seajs.org/docs/#docs |
@afc163 赞,好文章~ |
例子中这样得到模块a
那么怎么得到模块b或者c呢? |
一般来说,你不应该去拿 b 和 c ,因为 b 和 c 是作为 a 模块的子模块存在的,他们的功能是由 a 来封装或暴露的。 但是如果一定要拿,可以用 seajs.require 来获得: seajs.use('path/a', function(a) {
var b = seajs.require('path/b');
var c = seajs.require('path/c');
}); |
@afc163 好的,谢谢 |
关于id和路径, 不知道问什么没有采用/开头的绝对路径作为id?
|
@yessky 在线上时,js 经常存放在 cdn 上,与网站并不在一个根目录,还存在跨域等情况。用 |
错放在cdn上那就会配置别名或者直接使用请求地址,这个噩梦体现在? lifesinger notifications@github.com编写:
|
有时我们在更新迭代的时候会帮js加上一个版本号,比如 |
@huanghm 可以使用这种方式加版本号 |
把 jquery.js 直接放在 x-modules 目录下。或者把 jquery.js 里面的 id 修改成 jquery/jquery On Thu, Nov 7, 2013 at 10:23 AM, Reborn notifications@github.com wrote:
王保平 / 玉伯(射雕) |
看了还是有些不明吧啊。define 的 id 要和路径匹配,但是用grunt来transport如何自动加上路径啊 |
麻烦close掉 'lib': 'http://localhost:8080/spm_modules', 然后我使用了别名 alias: {
'lib/es5': 'lib/es5-shim/4.0.5/es5-shim',
'lib/json3': 'lib/json3/3.3.2/lib/json3',
'lib/jquery': 'lib/jquery/2.1.3/jquery',
'app/index': 'app/index/index'
} 但是我在 var $ = require('lib/jquery'); 还是返回 |
真是巨坑啊! |
所以说,只要合并后文件中的「主模块/入口模块」遵循「ID 与路径匹配原则」即可,其余的具名模块未必需要遵循「ID 与路径匹配原则」? |
define(function () { 不过为什么都引用jquery 不用zepto啊? |
如何用require 实现类似URL 参数后加上 "?ran=" + Math.random();的功能,求大神解答。 |
@Mrlilili jq 1.9.1是amd规范 |
@hoozi 没变成cmd模块之前也会返回null,是什么原因? |
收藏记录一下 |
您好,我是黄丽,您的邮件我已收到,谢谢
|
这是来自QQ邮箱的假期自动回复邮件。你好,我最近正在休假中,无法亲自回复你的邮件。我将在假期结束后,尽快给你回复。
|
ID 和路径匹配原则
经常收到
seajs.use
某具名模块时发现其引用为 null 的问题,或是移动了文件位置导致引用为 null
或者object is not function
的问题。比如这个 #954 ,这个 #888 ,这个 #879 ,这个 #739 ,这个 #696 ,还有这个 seajs/examples#12 。这些问题都指向 Sea.js 的一个基本约定原则:
ID 和路径匹配原则
。这是什么
所谓
ID 和路径匹配原则
是指,使用seajs.use
或require
进行引用的文件,如果是具名模块(即定义了 ID 的模块),会把 ID 和seajs.use
的路径名进行匹配,如果一致,则正确执行模块返回结果。反之,则返回null
。例如:或者在模块中 require :
当 jQuery 文件是下面的情况时,上述的变量
$
能拿到正确的返回结果。下面的代码则返回 null:
而匿名模块始终能正确返回结果:
为什么要有这个原则
回答这个问题前,请先阅读这篇文章:#426 。
首先,Sea.js 的模块启动接口秉承的是路径即 ID 的设计原则。
seajs.use
的方法的第一个参数被规定为文件路径(而不是 ID),这样的设计减轻了记忆模块 ID 的负担,无论是匿名模块还是具名模块,开发者只需要知道文件放在哪儿就行了。进一步的,之所以有这个
ID 和路径匹配原则
,是因为在 CMD 的书写规范中,一个文件对应一个模块,所有的模块都是匿名模块(即define(factory)
的形式)。那么当seajs.use
某模块时,这个模块对应的文件里的唯一的 define 方法理所当然的是这个模块的执行代码,这时可以正确返回结果。但是在生产环境下,静态文件不可避免地需要进行合并打包或者进行 combo,以优化请求数提高页面性能。这时,一个 js 文件可能有很多
define()
方法。那么请问,当
seajs.use
这个文件时,应该返回哪个模块?所以这时候 ID 就派上了用场,我们可以这样写:
我们定义好每个模块的 id ,在 Sea.js 里,那个和文件路径匹配的 ID 的模块就是这个文件的主模块。此时:
这个原则保证了我们能够自由合并模块来优化性能,seajs-combo 和 spm-build 的构建机制都是基于此原则。
在 RequireJS 中,也有类似的原则:http://requirejs.org/docs/errors.html#mismatch
更深一步
可能有人要问为啥一定要把 ID 定为文件路径,Sea.js 不是可以自定义 ID 吗,像下面这样:
上面的代码当然可以运行。但是有一点,任何一个模块的运行都涉及到两个步骤:
模块定义
和模块执行
,上面的代码两个步骤都包括在内。而使用了 Sea.js ,我们不希望用户去手动写script
标签引用模块。希望只需要seajs.use
模块的文件路径即可(入口唯一):Sea.js 会自动插入 script 标签,完成定义步骤,然后执行模块,拿到模块的输出。所以当一个文件里有多个 define 时,只能用 ID 是否匹配 use 中的路径来判断是否主模块。
当然可以回避掉这个原则,你只需要自己负责模块的定义部分,再自己
seajs.use
之前定义好的模块 ID 就行。或者通过 alias 来帮助 ID 匹配上最终的路径,这样就和 RequireJS 的方案基本一致了。
这样就不需要自己去引用上面的文件,可以直接通过 seajs.use 调用。
使用 spm-build 和 grunt 进行打包
我们推荐使用配套的构建工具来打包模块。
在 spm-build 中,所有的匿名模块通过标准的 transport 流程,会打包成具有实际 ID 的具名模块,而主模块(在 package.json 中指定输出的文件)的 ID 和实际路径是匹配的,符合
ID 和路径匹配原则
。如果没有使用官方工具,你需要在自己的打包和部署过程中保证这个原则。
历史
实际上在版本
1.3.1
之前,有一个特性叫做firstModuleInPackage
,即当一个文件里有多个 define 时,默认将第一个 define 里的模块作为主模块进行返回。由于各种原因我们去掉了这个特性,可以参见:#438 。小结
ID 和路径匹配原则
是 Sea.js 实现中的一个约定,这个约定帮助我们减少了对 ID 的记忆负担,同时增加了构建的复杂度。同样的,这也是一把双刃剑,目前还没有『完美』的处理方案,都会在某些地方存在取舍和权衡。如果这方面你有好的想法,欢迎与我们交流。
The text was updated successfully, but these errors were encountered: