动态加载require.js的依赖项

时间:2014-09-30 05:58:16

标签: javascript requirejs

我使用require.js加载项目的依赖项。像

这样的东西
var deps = [];
if( some condition )
    deps = [dep1, dep2, ...]
else
    deps = [other1, other2, ...]
define(deps, function(arg1, arg2, ....){

});

这对我来说很好。问题是当我缩小我的代码时,我遇到了以下问题:

Uncaught Error: Mismatched anonymous define() module: function (e,t.....

请帮助我解决任何知道解决方案的人。提前谢谢。

2 个答案:

答案 0 :(得分:1)

r.js将检测要包含在数组中的deps,但如果deps像您的情况一样是动态的,则不会被检测到

对于动态deps,您可以配置build.js文件以包含您将需要的动态deps以及模块

假设下面的代码

main.js

var x = 1;
var deps=[];
if(x > 0){
    deps = ['.\mod1'];
}
else{
    deps = ['.\mod2'];
}
define(deps, function(x){
    return x * 10;
});

mod1.js

define([], function(){
    return 5;
});

mod2.js

define([], function(){
    return 10;
});

r.js不会包含mod1和mod2与main,因为它们不是明确的deps,所以我们必须指示r.js mod1和mod2可能是main的deps,我们在build.js中这样做

build.js

({
    paths: {
    },
    shim: {
    },
    baseUrl: "app",
    removeCombined: true,
    findNestedDependencies: true,
    inlineText: true,
    optimizeAllPluginResources: true,
    stubModules: ['text'],
    dir: "app-dist",
    modules: [
        {
            name: "main",
            include: ["mod1","mod2"]
        }
    ]
})

通过这个设置,我们指示r.js包含mod1和mod2以及main.js

希望这很清楚

答案 1 :(得分:1)

问题

RequireJS'优化程序无法对运行时生成的依赖项执行依赖性分析。它至少能够以一种能够反映运行时发生的事情来执行你的代码的能力,并且仍然是它无法实现的情况处理。所以对于RequireJS'依赖关系分析要成功,你的依赖关系必须是字符串的字符串数组。在任何其他情况下,RequireJS将无法执行分析,并且它将无声地失败。

在您的情况下,这有两个后果:

  1. 优化器实际上并没有为您的模块命名。这解释了Mismatched anonymous define() module

    优化器的一个功能是为模块提供其最终名称。因此,您放入main.js的模块(例如,当它尚未优化时)将被转换,以便将其定义为define("main", ...。优化程序将名称添加到define调用的开头。 (仅当模块尚未命名时才会这样做。)

    如何判断优化器未命名您的模块?除了错误消息,这是一个主要线索,如果您查看r.js生成的内容,您会发现您的模块定义为define(deps,function。注意模块的第一个参数不是它的名字。

    你也会看到一个跟随它的存根。存根看起来像这个define("main",function(){})。只有当模块的代码不是实际的AMD风格的模块时,才应该存在此存根。例如,必须使用shim配置的模块将具有这些存根。但是,您的模块不需要此存根。

    无论如何,优化器完全混淆,并且没有正确命名模块。

  2. 优化程序找不到模块的依赖关系。

  3. 解决方案:调整Build

    mfarouk已经提到了如何修改你的构建,以便上面的第二个结果得到解决。我只是提到一般规则是这样的:你必须明确地为你的模块放入include优化器错过的所有模块的联合。它看起来像这样:

    modules: [
        ...,
        {
            name: "mymodule",
            include: [dependency1, dependency2, ...]
        },
        ...
    ]
    

    其中dependency1等是deps数组中的依赖项。

    要注意第一个后果,您需要额外的自定义。我建议使用优化器的onBuildRead选项:

    onBuildRead: function (moduleName, path, contents) {
        if (moduleName !== "main")
            return contents;
    
        return contents.replace(/define\(deps/,
                                'define("' + moduleName + '",deps');
    }
    

    优化程序读取每个模块时调用此函数。当它读取main时,会修改define调用以添加模块名称。然后,优化器将看到模块已经命名,将单独保留名称,并且不会生成虚假存根。