29

在我的主干应用程序中,我需要为每个所需文件提供后备,以防提供它们的 CDN 失败。

我试过require.onError这样覆盖:

require.onError = function (err) {
    if (err.requireType === 'timeout') {
        var url = err.requireModules;

        if (!!~url.indexOf("jquery/"))
            console.warn("CDN timed out, falling back to local jQuery.js")
            require(["libs/jquery"]);
            return;
        if (!!~url.indexOf("jqueryui/"))
            console.warn("CDN timed out, falling back to local jQueryUI.js")
            require(["libs/jqueryui"]);
            return;
        if (!!~url.indexOf("underscore"))
            console.warn("CDN timed out, falling back to local underscore.js")
            require(["libs/underscore"]);
            return;
        if (!!~url.indexOf("backbone"))
            console.warn("CDN timed out, falling back to local backbone.js")
            require(["libs/backbone"]);
            return;
    }
}

问题是这将异步加载回退文件。我需要按顺序加载这些文件,就像我使用order!插件的原始 require 语句一样。

使用 overridden onError:当 CDN 加载失败时,会启动 fallback 加载,但不等待。这带来了一个问题,因为脚本是根据它们的依赖关系加载的。这是我的原始require声明,这取决于 CDN:

require([
    "order!http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js",
    "order!http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js",
    "order!http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js",
    "order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js",
    "order!utils/date",
    "order!core/core",
    "order!core/errors",
    "order!core/constants"
], function() {
    ...
}
4

2 回答 2

58

您使用的是哪个版本的 RequireJS?看来您可能希望将 jQuery 的后备配置为配置中的路径,然后将 jQuery 设置为对需要它的其他模块的依赖。如果您使用 ~> 2.0,则类似于(未经测试):

// in your requirejs config
requirejs.config({
    //To get timely, correct error triggers in IE, force a define/shim exports 
    // check.
    enforceDefine: true,
    paths: {
        jquery: [
            'http://somecdn.com/jquery.min', // your cdn
            'lib/jquery' // your fallback
        ],
        jqueryui: "http://somecdn.com/jquery-ui.min.js"
    },
    shim: {
      jqueryui: ['jquery']
    }
});

// then in your requires
require([jquery, jqueryui, foo, bar], function($) {
    // stuff
});

他们在 wiki 中讨论如何做到这一点。如果您不使用 v2.x,这里也有一种处理方法。

如果所有模块都配置为指定它们自己的依赖项,那么您也不必担心order!指令。

于 2012-08-22T14:25:09.460 回答
20

我已经找到了 RequireJS 2.xx 中提供的问题的解决方案 有对这个解决方案的需求,所以反过来,RequireJSpaths在他们的配置中添加了一个对象。如果 CDN 失败,这将为 CDN 提供回退功能。

还需要注意的是,该order!插件在 Require 2.0 中已被弃用,所以我还需要利用shim对象来定义依赖关系。这实际上是一个非常有趣的想法。

这是我的新require.config:

require.config({
    urlArgs: "ts="+new Date().getTime(), // disable caching - remove in production
    paths: {
        jquery: [
            "http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min",
            "libs/jquery"
        ],
        jqueryui: [
            "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min",
            "libs/jqueryui"
        ],
        underscore: [
            "http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min",
            "libs/underscore"
        ],
        backbone: [
            "http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min",
            "libs/backbone"
        ]
    },
    shim: {
        'jqueryui': ['jquery'],
        'underscore': ['jquery'],
        'backbone': ['underscore'],
        'core/core': ['underscore'],
        'core/errors': ['core/core'],
        'core/constants': ['core/core']
    }
});
于 2012-08-22T14:25:41.830 回答