AMD:模块加载中的并发资源

时间:2014-07-29 10:56:24

标签: javascript requirejs amd

假设我有一个加载模块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,它可以使用template1template3”。

我认为使用require配置config可以解决问题:

// 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在加载资源后调用的回调函数,将资源传递给回调。但这会改变一些代码的工作流程。

我仍然有机会使用另一个模块加载器,所以如果另一个更适合该任务,欢迎提出建议。

1 个答案:

答案 0 :(得分:1)

这非常有趣。让我试着解决第一个问题:

我们说myModule.js是:

define(["mustache", "text!myTemplate.mt"], function(mt, template) {
    // ... A LOT OF CODE
    // ... THAT WILL TAKE
    // ... SOME TIME TO LOAD
});

因此,mustachemyTemplate.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很小,会很快加载。此外,它将开始并行加载其依赖项,即小胡子,模板和大部分代码,这就是您需要的效果。

看着它似乎是hackish;新的myModule.js需要知道myModuleMain.js的依赖关系,依赖关系必须保持同步并返回相同的对象。与需要main.js

中的所有内容相比,至少依赖关系更加本地化

如果您想要更加花哨,可以在构建或服务器中添加一个自动生成步骤,该步骤将从原始{{1}生成“新”myModule.jsmyModuleMain.js }。


另一个选择是使用myModule.js配置选项(ref)对项目的构建进行一些工作。该解决方案的概要是:

  1. 调整构建脚本以生成bundles,小胡子,模板的包;让生成的JS被称为myModule.js
  2. 配置捆绑包:

    myModuleBundle.js
  3. 现在要求bundles: { "myModuleBundle": ["myModule", "mustache", "text!myTemplate.mt"], ... } 将并行加载整个捆绑包。
  4. 如果其他模块也需要胡子,这显然是有缺陷的,因为它会加载多次。但是,如果在全局级别需要小胡子,那么从main要求它甚至使用myModule配置选项(ref)都不会有害。