load javascript file before onload with requirejs - javascript

I would like to use requireJS. However, I have a lib that needs to be loaded before the DOM. However, this is not what happens with requireJS
<html>
<head>
<script data-main="/app" src="/require.js"></script>
</head>
<body>
<bar-foo/>
</body>
</html>
With app.js
require.config({
paths: {
'customElement': '/customElement',
'barfoo': '/barfoo'
},
shim: {
barfoo: {
deps: [ 'customElement' ]
}
}
});
define(['barfoo'], function() {
....
}
For example, if I simply load this script directly in the head (without requireJS) it works fine. Is there a require-config-option so I can load a specific file immediately (synchronously?) ?

Requirejs is known for it's asynchronous power. However when you need some sort of an order in which you want files to be loaded due to dependencies, in require.config there is a shim config:
shim: 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.
So let's say you have a backbone app that depends on Underscore and jQuery, and you want them to load in that order then your would:
require.config({
paths: {
'Backbone': '/Backbone',
'Underscore': '/Underscore',
'jQuery': '/jQuery'
},
shim: {
'Backbone': [ 'Underscore', 'jQuery' ]
}
});
require(['Backbone'], function(Backbone){
//.....
});
So, RequireJS allows us to use the shim config to define the sequence of files which need to be loaded in correct order.

Related

What does requirejs.config() do?

I am having trouble understanding about requirejs.config() function.
requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-3.1.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1'
},
shim: {
'bootstrap': {
deps: ['jquery'],
exports: 'jQuery'
}
}
});
What does the function do? Please do not direct me to the documentation because I have read it and still found it confusing. I need a simple explanation on what this function does.
Are these scripts loaded asynchronously?
It creates aliases for script paths ant tells how to interpret bootstrap (non-AMD script) when loaded. Nothing is loaded yet. You have to require:
// we load two dependencies here
// `knockout` and `bootstrap` are expanded to values in config
// .js added to values
// callback function called when all dependencies are loaded
require(['knockout', 'bootstap'], function(Knockout, $) {
// jQuery is passed to this function as a second parameter
// as defined in shim config exports
});
The path is like declarations/definitions. So for example,
jquery: '../bower_components/jquery/dist/jquery',
you can later load this lib as follows.
define([
'jquery'
], function (jquery) {
//initialize or do something with jquery
}
You don't have to specify the absolute path of the library.
In shim, you will define dependencies. So for example,
paths: {
template: '../templates',
text: '../bower_components/requirejs-text/text',
jquery: '../bower_components/jquery/dist/jquery',
backbone: '../bower_components/backbone/backbone',
underscore: '../bower_components/underscore/underscore',
Router: 'routes/router'
},
shim: {
'backbone': ['underscore', 'jquery'],
'App': ['backbone']
}
Here backbone is dependent on underscore and jquery. So those two libs will be loaded before backbone starts loading. Similarly App will be loaded after backbone is loaded.
You might find this repo useful if you are familiar with backbone and express.
https://github.com/sohel-rana/backbone-express-boilerplate

Loading jQuery with RequireJS: different name convention in third-party libraries

I have an application using some third-party libraries as I also have some plug-ins created by myself using jQuery.
The point is: some third-party libraries are using $ and other ones jQuery as naming convention. The way I'm requiring jQuery through RequireJS is just as that:
[...]
var $ = require('jquery');
[...]
This way, I get the following console message as return:
Uncaught ReferenceError: jQuery is not defined jquery.scrolly.js:79
Uncaught TypeError: undefined is not a function
Then, I figured out a candidate solution by creating two variables and requiring jQuery in both:
var $ = require('jquery'),
jQuery = require('jquery');
So, as you can see this "solution" is redundant, unnecessary and unsophisticated — I need something consistent, something better.
Someone can share an idea with me?
Thanks to Daniel A. White, I could use an elegant-way solution called as shim config.
Let's do this step-by-step. My HTML is calling for app.js as require.js wants:
<!DOCTYPE html>
<head>
<!-- ... -->
<script data-main="js/app" src="js/require.js"></script>
</head>
<body>
<!-- ... -->
</body>
</html>
And this is my old js/app.js:
require.config({
baseUrl: 'js',
paths: {
jquery: 'vendor/jquery-2.1.1.min',
modernizr: 'vendor/modernizr-2.6.2.min',
scrolly: 'vendor/jquery.scrolly'
}
});
require(['main']);
Now, here the magic happens — see yourself my new js/app.js:
require.config({
baseUrl: 'js',
paths: {
jquery: 'vendor/jquery-2.1.1.min',
modernizr: 'vendor/modernizr-2.6.2.min',
scrolly: 'vendor/jquery.scrolly'
},
shim: {
'scrolly': {
deps: ['jquery'],
exports: 'scrolly'
}
}
});
require(['main']);
What's the big deal?
The greatness here is the simplicity as RequireJS thinks. As far I could understand, shim config is something like a "dependency manager" for libraries. For example, scrolly is a third-party library dependant of jQuery that have been already loaded — why then should we load it again? There's no need! We just need to inject its usefulness onto scrolly mechanisms that uses jQuery resources.
Another popular example is BackboneJS. Its single hard dependency is UnderscoreJS. To teach Backbone that Underscore is available for use, we supply its dependency through shim config as that:
[...]
shim: {
'backbone': {
deps: ['underscore'],
exports: '_'
}
}
[...]
So, that's it.

Unable to load crossroads.js using RequireJS

I try to load JS files using RequireJS , however crossroads http://millermedeiros.github.io/crossroads.js/ seems not be loaded properly. I have checked using Chrome Dev Toolbar and all JS files are actually loaded. However running window.crossroad returned me undefined?
Below is my requirejs config.. Kindly advice... Thanks!
index.html
<script data-main="scripts/config" src="scripts/require.js"></script>
config.js
require.config({
shim: {
"zepto.min": {
exports: "$"
},
"underscore.min": {
exports: "_"
},
"crossroads.min": {
exports: "crossroads"
} }
});
require(["zepto.min","underscore.min", "crossroads.min",], function() {
console.log("=> Loading app")
require(["main"]);
});
main.js
require(["hp-config", "hp-model", "hp-view", "hp-controller"], function () {
console.log("=> Init");
console.log(window.crossroads);
//$(document).ready( function(){ HP.C.init(); });
});
If you look at the code for crossroads, you'll see that it detects that it is in a AMD environment (which RequireJS is) and calls define by itself. So you should remove the shim you have for it. The basic rule is: a library that does not call define needs a shim but a library that calls define does not. The reason window.crossroads is undefined is that crossroads calls define instead of exporting itself in the global space (on window).
Given the require.config call you currently have, the updated call would be:
require.config({
shim: {
"zepto.min": {
exports: "$"
},
"underscore.min": {
exports: "_"
}
}
});
The above config is the minimum change required. However, I would also advise not using .min in the names you pass to require or define. So your config.js could be instead:
require.config({
paths: {
zepto: "zepto.min",
underscore: "underscore.min",
crossroads: "crossroads.min"
},
shim: {
zepto: {
exports: "$"
},
underscore: {
exports: "_"
}
}
});
require(["zepto","underscore", "crossroads",], function() {
console.log("=> Loading app")
require(["main"]);
});
This way, if you want to switch to the non-minified version (for debugging) you can just change the paths setting instead of having to go everywhere you require these modules and change the names.

Require JS is ignoring my config

I'm having pretty simple directory structure for scripts:
/js/ <-- located in site root
libs/
jquery-1.10.1.min.js
knockout-2.2.1.js
knockout.mapping.js
models/
model-one.js
model-two.js
...
require.js
config.js
Since the site engine uses clean URLs I'm using absolute paths in <script>:
<script type="text/javascript" data-main="/js/config.js" src="/js/require.js"></script>
RequireJS config:
requirejs.config({
baseUrl: "/js/libs",
paths: {
"jquery": "jquery-1.10.1.min",
"knockout": "knockout-2.2.1",
"komapping": "knockout.mapping"
}
});
Somewhere in HTML:
require(["jquery", "knockout", "komapping"], function($, ko, mapping){
// ...
});
So the problem is that RequireJS completely ignores baseUrl and paths defined in config file. I get 404 error for every module required in the code below. I see in browser console that RequireJS tries to load these modules from /js/ without any path translations:
404: http://localhost/js/jquery.js
404: http://localhost/js/knockout.js
404: http://localhost/js/komapping.js
However after the page is loaded and the errors are shown I type in console and...
> require.toUrl("jquery")
"/js/libs/jquery-1.10.1.min"
Why so? How to solve this problem?
It's my first experience using RequireJS, so I'm feeling like I've skipped something very simple and obvious. Help, please.
Update
Just discovered this question: Require.js ignoring baseUrl
It's definitely my case. I see in my Network panel that config.js is not completely loaded before require(...) fires own dependency loading.
But I don't want to place my require(...) in config because it is very specific for the page that calls it. I've never noticed such problem with asynchronicity in any example seen before. How do authors of these examples keep them working?
Solved.
The problem was that config file defined in data-main attribute is loaded asynchronously just like other dependencies. So my config.js accidentally was never completely loaded and executed before require call.
The solution is described in official RequireJS API: http://requirejs.org/docs/api.html#config
... Also, you can define the config object as the global variable require before require.js is loaded, and have the values applied automatically.
So I've just changed my config.js to define global require hash with proper configuration:
var require = {
baseUrl: "/js/libs",
paths: {
"jquery": "jquery-1.10.1.min",
"knockout": "knockout-2.2.1",
"komapping": "knockout.mapping"
}
};
and included it just BEFORE require.js:
<script type="text/javascript" src="/js/config.js"></script>
<script type="text/javascript" src="/js/require.js"></script>
This approach allows to control script execution order, so config.js will always be loaded before next require calls.
All works perfectly now.
Fixed the issue.
My config was being loaded asynchronously, and therefore the config paths weren't set before my require statement was being called.
As per the RequireJS docs Link here, I added a script call to my config before the require.js call. And removed the data-main attribute.
var require = {
baseUrl: '/js',
paths: {
'jquery': 'vendor/jquery/jquery-2.0.3.min',
'picker': 'vendor/pickadate/picker.min',
'pickadate': 'vendor/pickadate/picker.date.min'
},
shim: {
'jquery': {
exports: '$'
},
'picker': ['jquery'],
'pickadate': {
deps: ['jquery', 'picker'],
exports: 'DatePicker'
}
}
}
All is now working

Loading Backbone and Underscore using RequireJS

I'm trying to load Backbone and Underscore (as well as jQuery) with RequireJS. With the latest versions of Backbone and Underscore, it seems kind of tricky. For one, Underscore automatically registers itself as a module, but Backbone assumes Underscore is available globally. I should also note that Backbone doesn't seem to register itself as a module which makes it kind of inconsistent with the other libs. This is the best main.js I could come up with that works:
require(
{
paths: {
'backbone': 'libs/backbone/backbone-require',
'templates': '../templates'
}
},
[
// jQuery registers itself as a module.
'http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js',
// Underscore registers itself as a module.
'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.2.1/underscore-min.js'
], function() {
// These nested require() calls are just due to how Backbone is built. Underscore basically says if require()
// is available then it will automatically register an "underscore" module, but it won't register underscore
// as a global "_". However, Backbone expects Underscore to be a global variable. To make this work, we require
// the Underscore module after it's been defined from within Underscore and set it as a global variable for
// Backbone's sake. Hopefully Backbone will soon be able to use the Underscore module directly instead of
// assuming it's global.
require(['underscore'], function(_) {
window._ = _;
});
require([
'order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js',
'order!app'
], function(a, app) {
app.initialize();
})
});
I should mention that, while it works, the optimizer chokes on it. I receive the following:
Tracing dependencies for: main
js: "/home/httpd/aahardy/requirejs/r.js", line 7619: exception from uncaught JavaScript throw: Error: Error: Error evaluating module "undefined" at location "/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js":
JavaException: java.io.FileNotFoundException: /home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js (No such file or directory)
fileName:/home/httpd/aahardy/phoenix/trunk/ui/js/../../ui-build/js/underscore.js
lineNumber: undefined
http://requirejs.org/docs/errors.html#defineerror
In module tree:
main
Is there a better way of handling this? Thanks!
RequireJS 2.X now organically addresses non-AMD modules such as Backbone & Underscore much better, using the new shim configuration.
The shim configuration is simple to use: (1) one states the dependencies (deps), if any, (which may be from the paths configuration, or may be valid paths themselves). (2) (optionally) specify the global variable name from the file you're shimming, which should be exported to your module functions that require it. (If you don't specify the exports, then you'll need to just use the global, as nothing will get passed into your require/define functions.)
Here is a simple example usage of shim to load Backbone. It also adds an export for underscore, even though it doesn't have any dependencies.
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
}
}
});
//the "main" function to bootstrap your code
require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) { // or, you could use these deps in a separate module using define
});
Note: this simplified code assumes that jquery, backbone and underscore are in files named "jquery.js", "backbone.js" and "underscore.js" in the same directory as this "main" code (which becomes the baseURL for require). If this isn't the case, you'll need to use a paths config.
I personally think with the built-in shim functionality, the advantages of not using a forked version of Backbone & Underscore outweigh the benefits of using the AMD fork recommended in the other popular answer, but either way works.
Update: As of version 1.3.0 Underscore removed AMD (RequireJS) support.
You can use the amdjs/Backbone 0.9.1 and the amdjs/Underscore 1.3.1 fork with AMD support from James Burke (the maintainer of RequireJS).
More info about AMD support for Underscore and Backbone.
// main.js using RequireJS 1.0.7
require.config({
paths: {
'jquery': 'libs/jquery/1.7.1/jquery',
'underscore': 'libs/underscore/1.3.1-amdjs/underscore', // AMD support
'backbone': 'libs/backbone/0.9.1-amdjs/backbone', // AMD support
'templates': '../templates'
}
});
require([
'domReady', // optional, using RequireJS domReady plugin
'app'
], function(domReady, app){
domReady(function () {
app.initialize();
});
});
The modules are properly registered and there is no need for the order plugin:
// app.js
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone){
return {
initialize: function(){
// you can use $, _ or Backbone here
}
};
});
Underscore is actually optional, because Backbone now gets its dependencies on its own:
// app.js
define(['jquery', 'backbone'], function($, Backbone){
return {
initialize: function(){
// you can use $ and Backbone here with
// dependencies loaded i.e. Underscore
}
};
});
With some AMD sugar you could also write it like this:
define(function(require) {
var Backbone = require('backbone'),
$ = require('jquery');
return {
initialize: function(){
// you can use $ and Backbone here with
// dependencies loaded i.e. Underscore
}
};
});
Regarding the optimizer error: doublecheck your build configuration. I assume your path configuration is off. If you have a directory setup similar to the RequireJS Docs you can use:
// app.build.js
({
appDir: "../",
baseUrl: "js",
dir: "../../ui-build",
paths: {
'jquery': 'libs/jquery/1.7.1/jquery',
'underscore': 'libs/underscore/1.3.1-amdjs/underscore',
'backbone': 'libs/backbone/0.9.1-amdjs/backbone',
'templates': '../templates'
},
modules: [
{
name: "main"
}
]
})
For reference, as of version 1.1.1 (~Feb '13), Backbone also registers itself as an AMD module. It will work with requirejs without the need to use its shim config. (James Burke's amdjs fork also hasn't been updated since 1.1.0)
Good news, Underscore 1.6.0 now supports requirejs define !!!
versions below this require shims, or requiring underscore.js then blindly hoping that the "_" global variable hasn;t been smashed (which to be fair is a fair bet)
simply load it in by
requirejs.config({
paths: {
"underscore": "PATH/underscore-1.6.0.min",
}
});
I will write down directly, you can read the explaination on requirejs.org, you could use below code as a snippet for your everyday use; (p.s. i use yeoman) (since many things updated, im posting this as of Feb 2014.)
Make sure you included script in your index.html
<!-- build:js({app,.tmp}) scripts/main.js -->
<script data-main="scripts/main" src="bower_components/requirejs/require.js"></script>
<!-- endbuild -->
Then, in main.js
require.config({
shim: {
'backbone': {
deps: ['../bower_components/underscore/underscore.js', 'jquery'],
exports: 'Backbone'
}
},
paths: {
jquery: '../bower_components/jquery/jquery',
backbone: '../bower_components/backbone/backbone'
}
});
require(['views/app'], function(AppView){
new AppView();
});
app.js
/**
* App View
*/
define(['backbone', 'router'], function(Backbone, MainRouter) {
var AppView = Backbone.View.extend({
el: 'body',
initialize: function() {
App.Router = new MainRouter();
Backbone.history.start();
}
});
return AppView;
});
I hope I was useful.!
require.config({
waitSeconds: 500,
paths: {
jquery: "libs/jquery/jquery",
jqueryCookie: "libs/jquery/jquery.cookie",
.....
},
shim: {
jqxcore: {
export: "$",
deps: ["jquery"]
},
jqxbuttons: {
export: "$",
deps: ["jquery", "jqxcore"]
}
............
}
});
require([
<i> // Load our app module and pass it to our definition function</i>
"app"
], function(App) {
// The "app" dependency is passed in as "App"
// Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function
App.initialize();
});

Categories

Resources