Load timeout for run-time configuration in requirejs - javascript

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>
...

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.

requirejs config gives ReferenceError: can't find variable $

Maybe I have fundamentally misunderstood how requirejs config works but I thought my configuration below made some libraries global so I could just use them in other files while only having to require and define files that I needed to use within the individual script. However I cannot reference $ (jQuery) in my application code without getting a reference error indicating it is not globally accessible. I've isolated the problem to the simple example below.
My file set up is as follows:
test
|
|-index.html
|-TestApp.js
|-MainApp.js
|-lib
| |-require.js
| |-jquery.js
| |-loadash.js
| |-backbone.js
|-css
|-test.css
The library file versions are RequireJS 2.1.22, jQuery 2.0.3, Loadash 3.10.1 and Backbone 1.2.1. I'm just trying to set up my environment and the approach I am taking is to pass my TestApp.js file to require.js to load the required files and bootstrap the application code in MainApp.js. The script in index.html is as follows:
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' type='text/css' href='css/test.css'/>
</head>
<body>
<div></div>
<script src="./lib/require.js" type="text/javascript" data-main="./TestApp.js"></script>
</body>
</html>
The referenced css script file simply ensured the div is visible as an orange square. See below:
div {
height: 100px;
width: 100px;
background-color: #FA6900;
border-radius: 5px;
}
It's the script line in index.html that then kicks off the application code by passing my configuration file to requirejs. This is the TestApp.js passed across as data-main. The TestApp.js is here:
require.config({
paths: {
'jquery': 'lib/jquery',
'lodash': 'lib/lodash',
'backbone': 'lib/backbone'
},
map: {
'*': {
// Backbone requires underscore. This forces requireJS to load lodash instead:
'underscore': 'lodash'
}
},
shim: {
jquery: {exports: '$'},
underscore: {
deps: ['jquery'],
exports: '_'
},
backbone: {
deps: ['underscore'],
exports: 'Backbone'
},
TestApp: {
deps: ['backbone'],
exports: 'TestApp'
}
}
});
require(['MainApp'], function(MainApp) {
MainApp.run();
});
The file above references the paths to the library files I want to use, I then remap loadash to be loaded when underscore is required (I need some of the extra loadash capability), I then use the shim to ensure the dependancies are correct as the files are loaded. Passing this config file to require.js in the index.html seems to be working as all of the files are showing as loaded in my browser. However the problem seems to be they do not appear to be globally accessible as I thought they would be.
Following the config section the last require call loads the MainApp.js file and calls the exposed run function. The MainApp.js looks like this:
define(function(require) {
var run = function() {
$(document).ready(function() {
$('div').click(function() {
$('div').fadeOut('slow');
});
});
};
return {
run: run
};
});
As far as I understood I should not need to require the files I already mentioned in the require config, I thought they should be loaded and available to this code. This is where I have misunderstood what is going on or have missed a step out. The exposed run function is being called but the first line that calls $ throws the error:
ReferenceError: Can't find variable: $
So my questions are:
What have I got wrong in my thinking?
(or) What am I doing incorrectly?
What should I be doing in order to preload and make available
frequently referenced libraries so that I do not need to require and
define them in every file I have?
As far as I understood I should not need to require the files I already mentioned in the require config, I thought they should be loaded and available to this code.
You misunderstood how RequireJS works. You should read the documentation from start to finish. For now, here are things you should change.
You should require jquery in your MainApp module:
define(function(require) {
var $ = require("jquery");
You should remove your shims that you have for jquery, underscore and backbone as they all call define and shim is only for code that does not call define. I don't know what TestApp is but if it is your own code, you really should make it into a proper AMD module and remove the shim.
#Louis has made me realise the error in what I was doing above. Changing the shim in TestApp.js so that is reads:
MainApp: {
deps: ['backbone'],
exports: 'MainApp'
}
Corrected the problem, now Backbone, $ and _ are all available to the rest of my application code without cluttering up each files require. i.e. I do not need to begin every file with:
define (['lib/jquery', 'lib/loadash', 'lib/backbone'], function($, _ , Backbone) {
Given in my actual app the list of common deps is quite large this means I only need to define locally used resources and can control the paths from a single location.

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 to properly define shim config with requirejs

I have jQuery and a jQuery plugin loaded via RequireJS.
This is how my requirejs.config looks like:
requirejs.config({
baseUrl: "http://mysite.example.com",
"paths": {
// libraries
"jquery": "Static/js/library/jquery/jquery-1.10.2",
"jquery_sortable" : "Static/js/library/jquery-sortable/jquery-sortable",
shim: {
'jquery_sortable': ['jquery']
}
}
});
When I refresh the page two times or more very quickly, sometimes I get an exception in the plugin code that:
Uncaught ReferenceError: jQuery is not defined.
Basically, my plugin does not use the shim I have set for it.
What is the most reliable way to specify my shim config ??
Could be because you were not constructing as expected. As you notice you were putting shim inside paths. May be.
"paths": {
// libraries
"jquery": "Static/js/library/jquery/jquery-1.10.2",
"jquery_sortable" : "Static/js/library/jquery-sortable/jquery-sortable",
shim: {
'jquery_sortable': ['jquery']
}
}
-------EDIT AFTER COMMENT------
Maybe trying to define the dep as declared in the manual?
'foo': {
deps: ['bar'],
...
source: http://requirejs.org/docs/api.html#config-shim
It's weird because all the examples I have seen online put the shim config at the last bit of the requirejs.config but putting it at the top seemed to solve MY problem.
requirejs.config({
baseUrl: "http://mysite.example.com",
shim: {
'jquery_sortable': ['jquery']
},
"paths": {
// libraries
"jquery": "Static/js/library/jquery/jquery-1.10.2",
"jquery_sortable" : "Static/js/library/jquery-sortable/jquery-sortable"
}
});
I feel that this occurs because RequireJS is loading scripts asynchronously. This happens for performance reasons, i.e. scripts will be loaded in parallel. This is OK for normal AMD modules; RequireJS will keep the dependency tree from the define(["deps"], function(){...}) calls but will defer the execution of function() until its dependencies are resolved.
However with non-AMD, shimmed modules (like jQuery-UI), the entire script will be executed on load. This means that, if by any chance the "sortable" is loaded before "jquery", it will not find its dependency and fail as you write.
I believe the only robust workaround is to include jQuery as a plain old <script> tag, right after require.js. This way you cannot use the data-main attribute to load your entry point, you will have to require it separately:
<script src="scripts/lib/requirejs/require.js"></script>
<script src="scripts/lib/jquery/jquery.js"></script>
<script>
require(["app/bootstrap"]);
</script>

Require.js bug random Failed to load resource

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

Categories