Javascript AMD:模块加载中的并发资源
假设我有一个加载模块的应用程序Javascript AMD:模块加载中的并发资源,javascript,requirejs,amd,Javascript,Requirejs,Amd,假设我有一个加载模块的应用程序myModule。所述模块需要一些其他资源来工作(例如模板),因此myModule关心加载它所需的资源是很好的。事实上,这很容易: // main.js require(["myModule"], function(myModule) { // ... }); // myModule.js define(["mustache", "text!myTemplate.mt"], function(mt, template) { // ... });
myModule
。所述模块需要一些其他资源来工作(例如模板),因此myModule
关心加载它所需的资源是很好的。事实上,这很容易:
// main.js
require(["myModule"], function(myModule) {
// ...
});
// myModule.js
define(["mustache", "text!myTemplate.mt"], function(mt, template) {
// ...
});
然而,这里发生的事情是,首先加载模块的脚本,然后脚本加载它需要的资源。我想要实现的是同时开始加载myModule
和myTemplate
,以节省时间。我通过在main.js
中预加载资源来做到这一点:
// main.js
require(["myModule", "text!myTemplate.mt"], function(myModule) {
// ...
});
有没有更优雅的方式?尽管我认为没有办法避免main.js
必须“知道”myModule
的依赖关系
另一个问题
如果myModule
不需要它的资源,而是授予该模块,该怎么办?就像“我需要myModule
,它可以使用template1
和template3
”
我认为用一些config
配置require
可以达到以下目的:
// main.js
var templatesForMyModule = [...]
require.config({
config: {
myModule: templatesForMyModule
}
});
// myModule.js
define(["module", "mustache"], function(module, mt) {
var templates = module.config();
// ...
});
这里的问题是,我要么传递模板的路径(在加载myModule
之后加载,从而导致初始问题),要么传递模板的内容,但这意味着我必须在myModule
之前加载模板,这是我希望避免的另一件事。遗憾的是,我做不到
require.config({
config: {
myModule: require(templatesForMyModule)
}
});
然后,神奇地在myModule.js
中检索模板的内容
解决方案是:myModule
返回一个回调函数,该函数在加载资源后调用main
,将资源传递给回调函数。但这会改变一些代码的工作流程
我仍然有机会使用另一个模块加载器,因此如果另一个模块加载器更适合此任务,欢迎提供建议。这非常有趣。让我试着解决第一个问题: 假设您的
myModule.js
是:
define(["mustache", "text!myTemplate.mt"], function(mt, template) {
// ... A LOT OF CODE
// ... THAT WILL TAKE
// ... SOME TIME TO LOAD
});
因此,mustache
和myTemplate.mt
必须等待myModule.js
加载和解析。这是你的问题
为什么不将代码重新排列为:
// myModule.js
define(["myModuleMain", "mustache", "text!myTemplate.mt"], function(myModuleMain, mt, template) {
return myModuleMain;
});
// myModuleMain.js
define(["mustache", "text!myTemplate.mt"], function(mt, template) {
// ... A LOT OF CODE
// ... THAT WILL TAKE
// ... SOME TIME TO LOAD
});
现在myModule.js
很小,可以快速加载。此外,它将开始并行加载其依赖项,即mustache、模板和大部分代码,这是您需要的效果
看着它,它看起来很粗糙;新的myModule.js
需要知道myModuleMain.js
的依赖关系,这些依赖关系必须保持同步,并返回相同的对象。至少依赖项以这种方式更加本地化,而不是要求从main.js
开始的所有内容
如果你想变得更花哨,你可以在你的构建或你的服务器中添加一个自动生成步骤,从原始的myModule.js
生成“新的”myModuleMain.js
另一个选项是使用
bundles
configuration选项()对项目的构建进行一些工作。该解决方案的概要如下:
myModule.js
、mustache和模板组成的包;将生成的JS称为myModuleBundle.JS
bundles: {
"myModuleBundle": ["myModule", "mustache", "text!myTemplate.mt"],
...
}
myModule
将并行加载整个捆绑包如果其他模块也需要Mustach,这显然是有缺陷的,因为它会多次加载它。但是,如果在全局级别需要mustach,那么从main甚至使用
deps
configuration选项(),也不会有什么坏处。如果不在主脚本中静态声明依赖项,我认为这是不可能的。有趣的方法。第一个解决方案确实是黑客式的,并且引入了另一个HTTP请求。它的影响是需要考虑的,但最重要的是,目前我们无法使用任何有效的构建器,因此结果肯定是不可维护的。bundles
解决方案看起来非常有希望(我不知道这一点,我看到它是今年1月才推出的)。让我担心的是,如果我没有弄错的话,myModule
必须静态地声明其依赖项,而它可以访问的资源可能是动态的。是否有任何方法可以解决该模块所包含的捆绑包中的所有资源(不过我可以看到解决方法)?第二,您确定小胡子会多次加载吗?这对我来说听起来很奇怪,因为这有点违背了AMD loader的目的之一。(顺便说一句,我知道你为Require.js开发了一个懒惰的loader插件。)嗨,谢谢。我不确定我是否理解您所说的“myModule
必须静态声明其依赖项,而它可以访问的资源可能是动态的”…关于mustache被加载的问题,可能会有很多次-澄清:我的意思是,除了myModule
之外,可能还会有myThermodule
对mustache有类似的结构和要求。如果您制作了两个捆绑包,并且每个捆绑包中都包含胡子,因为它列在myModule
和mythermomodule
的依赖项中,那么它的代码将被下载两次。mustache模块将在AMD环境中声明一次,我的意思是下载时间将更长。