我们在开发过程中喜欢RequireJS和AMD,我们可以在其中编辑模块,在浏览器中点击重新加载,并立即看到结果。但是,当需要将我们的模块连接到一个文件中以进行生产部署时,显然必须仍然存在一个AMD加载程序,无论该加载程序是RequireJS本身还是其较小的合作伙伴"杏仁",如下所述:
http://requirejs.org/docs/faq-optimization.html#wrap
我的困惑是:为什么需要装载机?除非您有非常不寻常的情况,需要您在模块内部进行require()
调用,否则似乎可以在根本不存在加载程序的情况下连接一系列 AMD 模块。最简单的示例是如下所示的一对模块。
模.js:
define([], function() {
return {a: 1};
});
移动分贝.js:
define(['ModA'], function(A) {
return {b : 2};
});
给定这两个模块,似乎连接器可以简单地生成以下文本,而不会给生产服务器或浏览器带来 RequireJS 或 Almond 所需的额外带宽或计算负担。
我想象一个串联器生成(我正在使用 V 形引号 «,' 来显示上面两个模块的片段插入的位置):
(function() {
var ModA = «function() {
return {a: 1};
}»();
var ModB = «function(A) {
return {b : 2};
}»(ModA);
return ModB;
})();
据我所知,这将正确地重现AMD的语义,最少的无关的JavaScript胶水。有这样的连接器可用吗?如果不是,我会傻瓜认为我应该写一个吗 - 真的很少有代码库由用define()
编写的简单干净的模块组成,并且永远不需要进一步的require()
调用来启动以后异步获取代码?
下载的文件数量,还可以优化内存中加载的模块数量。
例如,如果您有 10 个模块并且可以将它们优化为 1 个文件,那么您已经节省了 9 次下载。
如果 Page1 使用所有 10 个模块,那就太好了。但是,如果 Page2 只使用 1 怎么办?AMD 加载程序可以延迟"工厂功能"的执行,直到模块require
'd。因此,Page2 仅触发单个"工厂函数"执行。
如果每个模块在require
时消耗 100kb 的内存,那么具有运行时优化的 AMD 框架也将在第 2 页上为我们节省 900kb 的内存。
这方面的一个例子可能是"关于框"样式对话框。它的执行被延迟到最后一秒,因为在 99% 的情况下无法访问它。例如(在松散的jQuery语法中):
aboutBoxBtn.click(function () {
require(['aboutBox'], function (aboutBox) {
aboutBox.show();
}
});
您可以节省创建与"关于框"关联的JS对象和DOM的费用,直到您确定有必要。
有关详细信息,请参阅 延迟执行定义,直到第一次需要 requirejs 对此的看法。
唯一真正的好处是,如果您跨部分使用模块,那么独立缓存模块是有好处的。
我也有同样的需要,所以我为此目的创建了一个简单的AMD"编译器"来做到这一点。你可以得到它 https://github.com/amitayh/amd-compiler
请注意,它缺少许多功能,但它可以完成工作(至少对我来说)。随意为代码库做出贡献。
如果您使用 require.js 将代码编译成一个用于生产的大文件,您可以使用 almond.js 来完全替换 require。
Almond 只处理模块引用管理,而不是不再需要的加载本身。
小心杏仁为了工作而施加的限制
理由没有像您提出的那样的构建工具。
上次*我查看优化器的输出时,它将模块转换为显式命名的模块,然后将它们连接在一起。它依赖于 require 自身来确保以正确的顺序调用工厂函数,并且传递正确的模块对象。要构建你想要的工具,你必须显式线性化模块 - 不是不可能,但更多的工作。这可能就是它没有完成的原因。
我相信**优化器具有自动将需求本身(或杏仁)包含在构建文件中的功能,因此您只需下载一次。这将大于您想要的构建工具的输出,但在其他方面相同。
如果有一个构建工具可以生成您要求的输出类型,则必须更加小心,以防同步require
,使用exports
而不是返回,以及任何其他CommonJS兼容性功能。
*那是几年前的事了。 我想是2010年。
**但现在似乎找不到它。