无法加载具有require配置路径和shim

时间:2015-11-03 12:57:54

标签: javascript requirejs amd

我已经加载了带有凉亭的把手,因此它位于供应商目录中。看来我已经配置了所有内容,我可以在检查器中看到handlebars.js文件被加载,它没有给出404 ...但据我所知,以下内容应该将它附加到全局命名空间(窗口)。正如您所看到的,我的模块已经“加载”并且工作正常,但在该模块中它依赖于把手 - ReferenceError: Handlebars is not defined

requirejs.config({
    baseUrl: "/scripts",
    urlArgs: "bust=" + (new Date()).getTime(),
    paths: {
        "jquery": "vendor/jquery/dist/jquery",
        "loaded": "vendor/loaded/dist/loaded",
        "handlebars": "vendor/handlebars/handlebars"
    },
    shim: {
        "loaded": {
            deps: ["jquery", "handlebars"],
            exports: "loaded"
        },
        "handlebars": {
            exports: "Handlebars"
        }
    }
});

requirejs(["app"]);

以下是已加载模块的片段(非AMD,使用shim配置加载):

if(typeof loaded === "undefined") loaded = {};

loaded.dispatch = (function() {

    // ...

    return {
        render: function () {

            // ...

            // gets this far, but error as the library is missing
            var template = Handlebars.compile(_template);

            // ...
        }
    }
})();

如上所述,我可以在检查器中看到Handlebars不是全局命名空间(窗口)的属性。从我读过的其他帖子中,我看不出我配错了什么。此外,由于需要加载,我不确定把手的问题是什么。

更新

作为把手版本的新main.js不需要它,它似乎:

requirejs.config({
    baseUrl: "/scripts",
    urlArgs: "bust=" + (new Date()).getTime(),
    paths: {
        "jquery": "vendor/jquery/dist/jquery",
        "loaded": "vendor/loaded/dist/loaded",
        "handlebars": "vendor/handlebars/handlebars"
    },
    shim: {
        "loaded": {
            deps: ["jquery", "handlebars"],
            exports: "loaded"
        }
    }
});

requirejs(["app"]);

1 个答案:

答案 0 :(得分:1)

您不需要(也不应该)垫片handlebars,因为库集成了UMD wrapper,因此与AMD pattern兼容(其中requirejs是实施):

if(typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
else if(typeof define === 'function' && define.amd)
    define([], factory);
else if(typeof exports === 'object')
    exports["Handlebars"] = factory();
else
    root["Handlebars"] = factory();

实际上,因为当库加载时会找到define函数,它不会将Handlebars附加到根对象(window)。 结果,显然,你的垫片无法找到它。

现在你的问题是你想要使用Handlebars,一个AMD加载的模块,非AMD模块。不幸的是,这不受官方支持:

  

仅使用其他" shim"模块作为shimmed脚本的依赖项,或者没有依赖项的AMD库,在它们创建全局(如jQuery或lodash)之后调用define()。否则,如果您使用AMD模块作为shim配置模块的依赖项,则在构建之后,可能不会在构建中的填充代码执行之后评估该AMD模块,并且将发生错误。最终的解决方法是将所有已调整的代码升级为可选的AMD define()调用。

没有好的解决方案。以下是一些想法:

(1)我仍然设法通过创建globalHandlebars模块来实现:

define(["handlebars"], function(Handlebars){
    window.Handlebars = Handlebars;
});

但这非常hacky并且没有得到官方支持。实际上,似乎无法保证在加载非AMD脚本之前调用dep define。我的笔记本电脑上从未发生过......

(2)另一种使其有效的方法是将handlebars作为脚本添加到您的html文件之前 requirejs(以便define尚未定义)。 仍然非常hacky,如果你也使用requirejs的把手,它将加载两次......

(3)显然,如果您可以将loaded脚本包裹在define电话中,那么效果最好,但我想这可能是不可能的。

(4)如果您使用优化工具,则还有一个wrapShim选项,但它并不总是有效,具体取决于您的填充代码的内容。

我没有任何其他解决方案,但requirejs人可能有一个解决方案。我很惊讶没有人在你面前绊倒这个问题。

您也可以考虑切换到browserifywebpack而不是requirejs(webpack本身支持AMD模块,而且有AMD loader用于browserify)。 此外,它们都可以让您预先构建模板(使用this loader表示webpack,或使用transform表示browserify),并避免包含整个handlebars库,这始终是一个好习惯。