RequireJS - 当在 define() 中指定模块 id 时

RequireJS - When specify module id in define()

在RequireJS文档(http://requirejs.org/docs/api.html#modulename)中,我无法理解这句话。

You can explicitly name modules yourself, but it makes the modules less portable

我的问题是

  1. 为什么显式命名模块会降低可移植性?
  2. 何时需要显式命名模块?

这就是命名模块便携性较差的原因,来自 Sitepen 的 "AMD, The Definite Source":

AMD is also “anonymous”, meaning that the module does not have to hard-code any references to its own path, the module name relies solely on its file name and directory path, greatly easing any refactoring efforts.

http://www.sitepen.com/blog/2012/06/25/amd-the-definitive-source/

来自 Addy Osmani 的 "Writing modular javascript":

When working with anonymous modules, the idea of a module's identity is DRY, making it trivial to avoid duplication of filenames and code. Because the code is more portable, it can be easily moved to other locations (or around the file-system) without needing to alter the code itself or change its ID. The module_id is equivalent to folder paths in simple packages and when not used in packages. Developers can also run the same code on multiple environments just by using an AMD optimizer that works with a CommonJS environment such as r.js.

http://addyosmani.com/writing-modular-js/

为什么需要一个明确命名的模块,再次来自 Addy Osmani "Writing modular javascript":

The module_id is an optional argument which is typically only required when non-AMD concatenation tools are being used (there may be some other edge cases where it's useful too).

Why explicitly naming module makes less portable?

如果你没有明确地给模块一个名字,RequireJS 可以自由地以任何它想要的方式命名它,这给了关于你可以用来引用的名字更多的自由到模块。假设您有一个文件 bar.js 的模块。你可以给 RequireJS 这个路径:

paths: {
    "foo": "bar"
}

并且您可以加载名为 "foo" 的模块。如果您在 define 调用中为模块命名,那么您将被迫使用该名称。这个问题的一个很好的例子是 jQuery。碰巧 jQuery 开发人员决定(我无法辨别出没有充分的理由)在 jQuery 的代码中对模块名称 "jquery" 进行硬编码。偶尔有人会抱怨他们的代码无法工作,他们的 paths 有这个:

paths: {
    jQuery: "path/to/jquery"
}

由于硬编码的名称,这不起作用。 paths 配置必须使用名称 "jquery",全部小写。 (map 配置可用于将 "jquery" 映射到 "jQuery"。)

When explicitly naming module needed?

当没有其他方式命名模块时需要它。 r.js 就是一个很好的例子,它将多个模块连接到一个文件中。如果在串联期间未命名模块,则无法引用它们。因此 r.js 为它连接的所有模块添加显式名称(除非你告诉它不要这样做或者除非模块已经命名)。

有时我会使用显式命名来命名 "glue" 或 "utility" 模块。例如,假设 jQuery 已经在 RequireJS 之前通过 script 元素加载,但我也希望我的 RequireJS 模块能够要求模块 jquery 访问 jQuery 而不是而不是依赖全球 $。如果我想在没有全局 jQuery 的上下文中 运行 我的代码,那么我不必针对这种情况修改它。我可能有这样一个主文件:

define('jquery', function () {
    return $;
});

require.config({ ... });

jquery模块只是为了满足需要jQuery的模块。将它放在一个单独的文件中没有任何好处,要正确引用它,必须明确命名它。