模块标识符 Module ids
有些模块需要依赖其他模块才能运行,正如我们在 编写 AMD 模块 中所讨论的。通过在依赖列表中罗列每个模块的标识符,或者执行“require”,当前模块的作者可以指定所依赖的其他模块。
模块标识符
AMD 和 CommonJS 都指定了看起来非常像文件路径或 URL 的模块标识符:由斜杠分隔的词条组成。词条的定义相当宽松。虽然 CommonJS 规范 进一步约束“词条”为驼峰式的 JavaScript 标识符,但是在实际使用中,其他的流行文件名(例如 -
)也是允许的。ES6 的模块规范 则更加宽松和实际,它要求标识符应该与文件系统和 URL 兼容。
AMD 保留了 !
字符,如果标识符中含有该字符,则表示用 加载器插件 来加载模块或其他类型的资源。
译注:格式为
[Plugin Module ID]![resource ID]
,例如text!../templates/start.html
。
一些合法的模块标识符示例:
"wire/lib/functional"
"poly/es5-strict"
"app/billing/billTo/Customer"
"jquery"
与文件系统和 URL 一样,模块标识符中的斜杠描述了层次结构。通常情况下,层次结构与文件系统的目录结构是相同的,但是无法百分百保证。例如,curl.js 暴漏了一些扩展 API 模块,这些模块的标识符格式是“curl/submodule”,但是它们并不是真实存在的文件。
注意大小写是否正确。尽管大部分模块通常映射到了文件,即模块标识符的拼写和大小写与文件名完全一样。例如,“jQuery”就不是正确的模块标识符(大写了“Q”)!下面的代码演示了如何在一个模块中加载 jQuery:
define(function (require) {
var $ = require('jquery');
$('body').text('Hello world!');
});
保留标识符
大多数 AMD 环境会保留几个特殊的模块标识符,用来引用内置模块或工具。例如,标识符“require”、“exports”和“module”用于模拟 CommonJS 中的同名变量,以此来访问伪模块。AMD 环境可能还保留了一些其他的标识符。例如,curl.js 0.8 的一个推荐特性是伪模块 global
,用来帮助开发人员编写可以同时运行在服务器和浏览器的代码。
define(function (require) {
// inspect the CommonJS "module" var
var module = require('module');
console.log(module.uri, module.id);
});
关于保留标识符的详细信息,请查阅你正在使用的 AMD 环境的文档。
相对标识符
AMD 和 CommonJS 也支持相对标识符概念。处于同一层级下的模块,可以通过以 .
开头的标识符来引用。处于上一层级的模块,则通过 ../
来引用。
在运行时或构建时,AMD 环境必须将相对标识符转换为绝对标识符。绝对标识符位于模块层级的顶层,并且不包含 ..
和 .
。移除起始 ..
和 .
的过程称为“规范化 normalization”。例如,假设当前模块的标识符是 app/billing/billTo/Customer
,AMD 环境会像下面这样规范请求的标识符:
// module app/billing/billTo/Customer
define(function (require) {
// normalizes to "app/billing/billTo/store"
var store = require("./store");
// normalizes to "app/billing/payee/Payee"
var Payee = require("../payee/Payee");
});
AMD 和 CommonJS 也可以把单个的 .
和 ..
解释为模块标识符。.
被规范为与当前层级同名的模块,..
被规范为与上一层级同名的模块。是的,太混乱了!也许这就是很少看到它们被使用的原因。但愿举一些例子会有所帮助。例如,当前模块是 “app/billing/billTo/Customer”,AMD 环境会像下面这样规范请求的标识符:
// module app/billing/billTo/Customer
define(function (require) {
// normalizes to "app/billing/billTo" (a module, not a folder!)
var billTo = require(".");
// normalizes to "app/billing" (a module, not a folder!)
var billing = require("..");
});
提示:永远不要使用相对标识符来引用不相关的模块!相对模块适用于在同一个“包 package”(后面再定义它)中的场景。此外,多个 ../
是一种不好的代码味道,意味着你需要更好地组织你的模块。在 AMD 环境中,相对标识符还可能被解释为一个 URL 而不是标识符。
// module app/billing/billTo/Customer
define(function (require) {
// OK: normalizes to "app/common/payee/Payee"
// food for thought: should common and billing be separate packages?
var Payee = require("../../common/payee/Payee");
// BAD: normalizes to "../util/date" -- a URL, not an ID!
var Date = require("../../../util/Date");
// GOOD: use an absolute id to reference a different package
var Date = require("util/Date"); // "Date" module in the "util" package
});
那么,如果我指定了标识符(而不是 URL),AMD 环境中是如何知道去哪里查找模块的呢?
那是 定位 AMD 模块 的主题了。
blog comments powered by Disqus