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环境中声明一次,我的意思是下载时间将更长。