In my backbone app, I need to provide a fallback for each required file, in the case that the CDN that delivers them fails.
I have tried overwriting require.onError
like so:
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;
}
}
The problem is that this will asynchronously load the fallback files. I need these files to load in order, just like the original require statement, where I use the order!
plugin.
With the overridden onError
: when the CDN fails to load, the fallback load is started, but not waited for. This presents a problem because the scripts are ordered to be loaded based on their dependencies. Here is a look at my original require
statement, that depends on the 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() {
...
}
Falling back from CDN to local copies of jQuery and JavaScript. The basic idea for CDN fallback is to check for a type or variable that should be present after a script load, and if it's not there, try getting that script locally. Note the important escape characters within the document.write.
RequireJS is a JavaScript file and module loader. It improves perceived page load times because it allows JavaScript to load in the background. In particular, it enables asynchronous JavaScript loading.
As per RequireJS API documentation, shim lets you. Configure the dependencies, exports, and custom initialization for older, traditional "browser globals" scripts that do not use define() to declare the dependencies and set a module value. - Configuring dependencies.
Advertisements. RequireJS can be initialized by passing the main configuration in the HTML template through the data-main attribute. It is used by RequireJS to know which module to load in your application. For instance − <script data-main = "scripts/main" src = "scripts/require.js"></script>
What version of RequireJS are you using? It seems you might want to configure jQuery's fallback as a path in your config, then set up jQuery as a dependency on the other modules that need it. If you're using ~> 2.0, something like (untested):
// 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
});
They talk about how to do it in the wiki. If you are not using v2.x, there is a method for handling that here too.
If all the modules are configured to specify their own dependencies, you shouldn't need to worry about the order!
directives either.
I have found a solution to the problem provided in RequireJS 2.x.x. There was a demand for this solution, so in turn, RequireJS added a paths
object to their config. This provides fallback functionality for CDNs, should they fail.
It should also be noted that the order!
plugin has been deprecated in Require 2.0, so I also needed to make use of the shim
object to define dependencies. It's actually a pretty interesting idea.
Here is my new 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']
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With