Require.js bug random Failed to load resource - javascript

My application use require.js, I have a random bug (happens 1 time for 50 reload)
Require.js write in the console :
Failed to load resource: the server responded with a status of 404 (Not Found)
Indeed, require.js try to include jquery from a wrong directory...
I don't know why, most of the time the application works fine...
My config is pretty simple :
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
animate_from_to: {
deps: ['jquery']
},
bootstrap: {
deps: ['jquery']
},
zoom: {
deps: ['jquery']
},
shop_util: {
deps: ['jquery']
},
pricer: {
deps: ['jquery']
},
filter: {
deps: ['jquery']
},
paginator: {
deps: ['jquery']
},
},
paths: {
bootstrap: 'lib/bootstrap',
jquery: 'lib/jquery-1.9.1',
zoom: 'lib/jquery.zoom.min',
animate_from_to: 'lib/jquery.animate_from_to-1.0.min',
backbone: 'lib/backbone.min',
underscore: 'lib/underscore.min',
text: 'lib/require-text',
shop_util: 'lib/shop_util',
pricer: 'lib/pricer',
filter: 'lib/filter',
paginator: 'lib/paginator',
}
});
Thank you

It seems you have another entry point into your application somewhere other than your data-main script (js/main.js). Even if it's a subsequent script in the same page, you cannot depend on your data-main script being completed before the next script runs, since it's loaded with async attribute.
<script data-main="js/main" src="js/lib/require.js"></script>
<!-- foo.js might run before js/main.js !!! -->
<script src="js/foo.js"></script>
You can prove this by adding a console.log statement at the end of js/main.js and one in foo.js (or whatever). Normally you will see the one from js/main.js and then foo.js , but in that 1 out of 50 case you'll see them happen in the other order.
There are several strategies to deal with this:
1 - Do all your app initiation and subsequent require's from your data-main script
Applies to single-page apps, of course. All in one file:
require.config({
// snip
});
require(['mymodule'], function( mymodule ) {
// do stuff
});
2 - Use an inline script right after the require.js script tag
Instead of having the above script inside a separate file referenced by data-main, just have a 2nd script tag right below. This is the first example listed in the docs.
Applies mostly to single-page-apps
3 - Load your require config into global variable prior to the require.js script tag
Second example listed in the docs.
<script>
var require = {
paths: { // define them}
shim: { // define them }
};
</script>
<script src="scripts/require.js"></script>
Applies mostly to single-page-apps
4 - Nest your require calls to load the the config first
This works best for multi-page apps and is the one recommended in the multi-page shim app example
<script src="js/lib/require.js"></script>
<script>
//Load common code that includes config, then load the app
//logic for this page. Do the require calls here instead of
//a separate file so after a build there are only 2 HTTP
//requests instead of three.
require(['./js/common'], function (common) {
//js/common sets the baseUrl to be js/ so
//can just ask for 'app/main1' here instead
//of 'js/app/main1'
require(['app/main1']);
});
</script>
Related questions here, here, and here

Related

RequireJS is loading scripts that are not needed on all pages

Require.js loads every module on every page, so I get JavaScript errors on pages that don't need the loaded scripts. Specifically, the news-filter.js is loading on my search page, and causing the error:
jquery-1.12.3.min.js:2 Uncaught Error: Syntax error, unrecognized expression: "li." from this line in the news-filter.js
$("ul.mediaListing").children("li."+chosenYear).filter("."+chosenCategory).each(function(c) {
Am I missing somthing about how reqire.js determines what scripts are needed on each page?
My main.js file is:
requirejs.config({
baseUrl: [system-view:internal]"/render/file.act?path=/assets/scripts/"[/system-view:internal] [system-view:external]"/assets/scripts/"[/system-view:external],
paths: {
"jquery": "libs/jquery/jquery-1.12.3.min",
"velocity": "libs/velocity/velocity",
"bgstretch": "plugins/background-stretch/background-stretch",
"campus-map": "modules/campus-map",
"velocity-ui": "libs/velocity/velocity.ui",
"slick": "plugins/slick/slick",
"iscroll": "plugins/iscroll/iscroll",
"dotdotdot": "plugins/dotdotdot/jquery.dotdotdot.min.umd",
"select": "plugins/select/select",
"accordion": "modules/accordion",
"news-filter": "modules/news-filter",
"codebird": "modules/codebird",
"social-feed": "modules/social-feed"
},
shim: {
"slick": ["jquery"],
"select": ["jquery"],
"bgstretch": {
deps: ["jquery"]
},
"accordion": ["jquery"],
"codebird": ["jquery"],
"social-feed": {
dep: ["jquery", "codebird"],
exports: "displayFeed"
},
"campus-map": {
deps: [ "jquery" ]
},
"velocity": {
deps: [ "jquery" ]
},
"velocity-ui": {
deps: [ "velocity" ]
}
},
map: {
'*': {
'jQuery': 'jquery'
}
}
});
requirejs(
['jquery', 'modules/utils', 'modules/custom.ui', 'libs/jquery/paginga.jquery', "modules/social-feed", "modules/news-filter"],
function ($, utils, ui, paga, social, news) {
ui();
$(".paginate").paginga({
// use default options
});
});
I like a very modular approach and RequireJS has a lot of different ways to use it. I'll share how I typically have it set up which accomplishes what you are looking for, is streamlined and makes it easy to implement and understand.
I avoid having anything require in my main js completely. First I will create a bundle that includes both the base require.js and a JS file I create called config.js. I will have this bundle loaded in my layout page so it's always available. If you aren't using MVC, the idea is just to make sure Require and my custom config file are always loaded together and always available so do what you need to for that.
Config.js is very simple, in your case just taking your code it will look like this:
var require = {
baseUrl: [system-view:internal]"/render/file.act?path=/assets/scripts/"
[/system-view:internal] [system-view:external]"/assets/scripts/"[/system-
view:external],
paths: {
"jquery": "libs/jquery/jquery-1.12.3.min",
"velocity": "libs/velocity/velocity",
"bgstretch": "plugins/background-stretch/background-stretch",
"campus-map": "modules/campus-map",
"velocity-ui": "libs/velocity/velocity.ui",
"slick": "plugins/slick/slick",
"iscroll": "plugins/iscroll/iscroll",
"dotdotdot": "plugins/dotdotdot/jquery.dotdotdot.min.umd",
"select": "plugins/select/select",
"accordion": "modules/accordion",
"news-filter": "modules/news-filter",
"codebird": "modules/codebird",
"social-feed": "modules/social-feed"
},
shim: {
"slick": ["jquery"],
"select": ["jquery"],
"bgstretch": {
deps: ["jquery"]
},
"accordion": ["jquery"],
"codebird": ["jquery"],
"social-feed": {
dep: ["jquery", "codebird"],
exports: "displayFeed"
},
"campus-map": {
deps: [ "jquery" ]
},
"velocity": {
deps: [ "jquery" ]
},
"velocity-ui": {
deps: [ "velocity" ]
}
},
map: {
'*': {
'jQuery': 'jquery'
}
}
};
That's it. I tend to have all of my javascript files associated to each HTML page separated, so in the paths section of the set up I'll have the view name and then the location in my source of the corresponding javascript file. Then in my HTML page when I'm adding in scripts, I'll simply state
<script> require(['sign-in']); </script>
This will grab the script file I have defined in the require variable for my view. Then in each script file, sign-in.js for example for this one, I will wrap all of the scrip in a define statement, so at the top of each JS file you can clearly see what dependencies you will load and use in that page. It's clean, it's a framework, it works wonderfully, and it keeps you from loading things you don't need.
In the self contained JS file you would do:
define(['jquery', 'lodash', 'bootstrap'], function ($, _) {
//All JS code here
}):
I will have all my libraries that need a selector defined first and then everything else after. That's it, hopefully a real example will help you.
Am I missing somthing about how reqire.js determines what scripts are needed on each page?
Sure looks like you are. You show a main.js file that has this (reformatted to help readability):
requirejs(['jquery', 'modules/utils', 'modules/custom.ui',
'libs/jquery/paginga.jquery', "modules/social-feed",
"modules/news-filter"],
If you use this main.js on all your pages, then all the modules you list there are going to be loaded, which means that modules/news-filter is going to be loaded on all pages. This, irrespective of whether any code actually uses it.
The way RequireJS works, any dependency listed in a require call is loaded. And for each module loaded, any dependency they list in their define call or in a shim set for them in your configuration is also loaded. It does not matter one bit if something is listed but not actually used by your code.
Tangential remark about your configuration. In your paths you have:
"news-filter": "modules/news-filter"
But then you refer to it as modules/news-filter in your require call instead of news-filters. You should use news-filter or remove the mapping you've set in paths. RequireJS does now allow referring to the same JavaScript file through two different module names in the same context. If you load your module as modules/news-filter in one place and as news-filter somewhere else, you're going to run into problems.
If you need to use two different names to access the same JavaScript file, you use map. What map does is tell RequireJS "when you get a request for module X, load module Y instead". So RequireJS replaces the module name requested with a different one.

Trouble linking form2js file to project with require.js

I want to use form2js to convert a form's info to json to post. The problem is, the framework I am using uses require.js and it seems like I am not linking the form2js file with the requirejs config properly. I am getting an
Uncaught ReferenceError: form2js is not defined
error.
form2js is a function within the form2js.js file.
Here is the config file:
require.config({
baseUrl: "assets/js/lib/"
, shim: {
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'underscore': {
exports: '_'
},
'bootstrap': {
deps: ['jquery'],
exports: '$.fn.popover'
},
'form2js': {
exports: 'form2js'
}
}
, paths: {
app : ".."
, collections : "../collections"
, data : "../data"
, models : "../models"
, helper : "../helper"
, templates : "../templates"
, views : "../views"
}
});
require([ 'app/app'], function(app){
app.initialize();
});
And in the main html page I run this:
<script data-main="assets/js/main.js" src="assets/js/lib/require.js" ></script>
Any guidance to the right resources would be very appreciated!
Including form2js in require.config just tells it where to find the form2js module (and other information, like it's dependencies, etc.)
To actually load form2.js you have (and hence define the form2js global), you have to list it as a dependency in the module where you are using it.
For example assuming your initialize() function uses it, your last statement would be
require([ 'app/app', 'form2js' ], function(app){
app.initialize();
});
Note - if app/app.js uses form2js, you have to include it in the define for that module. You might also want to check (in your browser developer tools network tab if form2.js was actually loaded, once you list it as a dependency somewhere)

Load textext.js plugin with require.js

I'm trying to load textext.js jquery plugin, with one of it's plugins, textext tags. On my project, I'm using require.js in order to load all scripts with it's dependencies.
As used for other scripts, I'm using a shim config on my main.js file:
main.js
require.config({
shin: {
jquery: {
exports: '$'
},
'textext': {
deps: ['jquery'],
exports: '$.fn.textext'
},
'textext_tags': {
deps: ['jquery', 'textext'],
}
},
paths: {
jquery: 'lib/jquery-min',
textext: 'lib/textext/textext.core',
textext_tags: 'lib/textext/textext.plugin.tags',
}
});
On the page that I use it, I call it as above:
file-app.js
define([
'jquery',
'textext',
'textext_tags',
], function($, Textext, TextextTags) {
// do stuff
});
The code is loading and working correctly on firefox, but on Chromium, sometimes (about 2/3 of the times), at the first time that I load the page, I've receive the following error, that broke the functioning of the page:
TypeError: Cannot set property 'TextExtTags' of undefined
#3 localhost/js/lib/textext/textext.plugin.tags.js:23:27
Inside the file textext.plugins.tags.js, we have at line 23 (the failure line):
$.fn.textext.TextExtTags = TextExtTags;
So, inspecting it with Firebug, I realize that Jquery is not loaded, so $ and $.fn is undefined.
My question is: why this schema of require.js is working with other jQuery plugins on the same project (like jquery cookie and others), but not with this, a jquery plugin with it's subplugins?
As Vishwanath said, only changing from "shin" to "shim" worked, like above:
require.config({
shim: {
jquery: {
exports: '$'
},
...
Thanks!

How are you supposed to use RequireJS to do CDN failover if you need it to work with IE7+?

We have a website that uses several 3rd party javascript libraries, and where possible we'd like to serve them from CDNs to reduce the number of requests on our server. Recently, one of our clients reported a problem using our site, and as it turns out it was because they were blocking one of the CDNs we use (ajax.aspnetcdn.com!). We had been thinking out implementing a failover for the CDNs for sometime but have never gotten around to doing it, and now my manager is pushing us to solve it ASAP.
As is often the case, Scott Hanselman's blog seemed to offer some potential answers, suggesting tools like yepnope and RequireJS. Yepnope has been deprecated, so we chose RequireJS.
We have implemented RequireJS on our site (not a huge job), only to find out it doesn't quite work correctly in IE (absolutely perfect in all other major browsers).
Following the documentation (and some advice from other posts on here), we have set it up as follows. We have this script tag in our html head tag:
<script data-main="/Scripts/main.js" src="/Scripts/require.js" type="text/javascript"></script>
Then in main.js we have configured RequireJS
requirejs.config({
enforceDefine: true,
paths: {
jquery: [
"https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min",
"jquery"
],
jqueryui: [
"https://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min",
"jqueryui"
],
jqueryunobtrusiveajax: [
"https://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.min",
"jqueryunobtrusiveajax"
],
jqueryvalidate: [
"https://ajax.aspnetcdn.com/ajax/jquery.validate/1.7/jquery.validate.min",
"jqueryvalidate"
],
jqueryvalidateunobtrusive: [
"https://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min",
"jqueryvalidateunobtrusive"
],
site: [
"site"
],
localisation: [
"localisation"
]
},
shim: {
jqueryui: {
deps: ['jquery'],
exports: "$"
},
jqueryvalidate: {
deps: ['jquery'],
exports: '$'
},
jqueryvalidateunobtrusive: {
deps: ['jquery', 'jqueryvalidate'],
exports: '$'
},
jqueryunobtrusiveajax: {
deps: ['jquery'],
exports: '$'
},
localisation: {
deps: ['jquery', 'jqueryui', 'jqueryvalidate'],
exports: '$'
},
site: {
deps: ['jquery', 'jqueryui', 'jqueryvalidate', 'jqueryvalidateunobtrusive'],
exports: '$'
}
}
});
Note that as per the advice on how to "Catch load failures in IE" on RequireJS's GitHub Wiki we have set enforceDefine to true, and used define() to define a module (we want the same scripts on every page) before using require(), like this:
define('main', ["jqueryui", 'jqueryvalidate', 'jqueryvalidateunobtrusive', 'jqueryunobtrusiveajax', 'localisation', 'site'], function () {
// we have some code here that confirms each script is loaded, looks a bit like this (one for each script):
if (jQuery) {
console.log("jQuery");
} else {
console.error("jQuery");
}
});
Then on each page we simply add the following script tag:
<script type="text/javascript">
require(["main"], function() {
// any page specific script goes here
});
</script>
This works just fine in all browsers (including IE), BUT it does not work in IE if you block any of the CDNs. Oddly it works just fine if you change the url for CDN files to something that doesn't exist, or remove the CDN url entirely (so just serve the local file). If I block the CDN by adding the domain to internet options -> security -> restricted sites in IE, it takes ages (5-10 secs) attempting to load the scripts, then times out on the two local only files (site.js and localisation.js):
SCRIPT5022: Load timeout for modules: localisation,site http://requirejs.org/docs/errors.html#timeout
All the other browsers cope just fine if I block the CDNs (using AdBlock Plus), does anyone know why I am experiencing this behaviour with IE?

Load timeout for run-time configuration in requirejs

I am getting load timeout error for the run-time configuration and common.js is my run-time configuration
As you can see below that I have defined waitseconds equal to 0 for the files that will be loaded from common.js however I am getting loadTimeout for the common.js itself.
index.html
<script type="text/javascript" src="js/vendor/require.js"></script>
<script>
require(['./js/common'],
function (common) {
'use strict';
require(['plot/app', 'es6shim']);
});
</script>
common.js
requirejs.config({
baseUrl: 'js',
waitSeconds: 0, // Allowing the browser to load all modules without time limit
paths: {
// 3rd party
es6shim: 'vendor/es6-shim.min',
jquery: 'vendor/jquery-1.10.1.min',
jqueryUI: 'vendor/jquery-ui.min',
lodash: 'vendor/lodash.min',
mockjax: 'vendor/jquery.mockjax',
hammer: 'vendor/hammer.min'
},
shim: {
mockjax: { deps: ['jquery'] },
jqueryUI: { deps: ['jquery'] },
hammer: { deps: ['jquery', 'jqueryUI'] }
}
});
Let me know what can be done in this case as the common.js is itself sometimes not getting loaded and thus throwing load timeout error.
Note:- Due to build configuration I am not writing the run-time configuration in the index.html as the configuration(common.js) is common for other app.
Your question does not appear to be seeking to get to the bottom of why common.js may be taking so long to retrieve that a timeout is triggered. It seems a litle odd that a timeout should be occurring loading such a simple script, but I assume that is not a concern for you at this point.
To increase the timeout before loading common.js, try putting something like the following in index.html to provide baseline RequireJS configuration settings to be applied before common.js is loaded:
<script>
require = { waitSeconds: 0 };
</script>
<script type="text/javascript" src="js/vendor/require.js"></script>
...

Categories