A method for loading the backbone stack with require - javascript

Here is how I would do it using plain HTML script tags per this SO Question on CDN suggestions. This would be a serial load (underscore->jquery->backbone) that holds up the rest of the page.
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js"></script>
How would I load these libraries using require.js or a similar non-blocking method?
References ( links to the API )
underscore
jQuery
backbone
require

jquery is AMD Friendly so you can just require it in your require.js config
Backbone and underscore are no longer AMD Friendly so you have these options:
You can either include them as "externals", with shim assigning the correct dependencies (see here the docs and a tutorial )
Or you can use slightly altered versions of both libraries that are AMD enabled. You can find them in this repository.
Use an older version of backbone and underscore. (not recommended)
Note: If you opt for the shimming route, keep in mind that those libraries will not be load asynchronously.
Here's a working example using the ALTERED VERSIONS of the library:
require.config({
enforceDefine: true, //Only libraries AMD Friendly will be loaded
urlArgs: "bust=" + (new Date()).getTime(), //for development, forces browser to clear the cache
paths: { // relative paths (to the current file main.js)
"es5": 'libs/es5-shim/es5-shim',
"jquery": 'libs/jquery/jquery',
"jqueryThreeDots": 'libs/jquery/plugins/jquery.ThreeDots',//A jquery plugin
"underscore": 'libs/underscore/underscore.amd',
"underscore.string": 'libs/underscore/underscore.string',
"backbone": 'libs/backbone/backbone.amd',
"text": 'text',
"mediator": 'libs/backbone/plugins/backbone.mediator',
"bootstrap": 'libs/bootstrap/bootstrap.min',
"rangy": 'libs/rangy/rangy-core.amd',
},
shim: {
"bootstrap": {
deps: ["jquery"],
exports: "$.fn.popover"
}
}
});
An example with shim:
require.config({
enforceDefine: true,
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
"jquery": 'http://code.jquery.com/jquery-1.9.1.min.js'
},
shim: {
backbone: {
deps: ["underscore", "jquery"], // Backbone dependencies
exports: "Backbone" // variable exported
},
underscore: {
exports: "_"
}
}
});

This is how we include jQuery, Underscore and Backbone with Require in our projects:
requirejs.config({
baseUrl: "js",
paths: {
backbone: "backbone-min",
jquery: "jquery.min",
underscore: "underscore-min"
},
shim: {
backbone: { deps: ["underscore", "jquery"], exports: "Backbone" },
jquery: { exports: "jQuery" },
underscore: { exports: "_" }
}
});
requirejs(["backbone"], function (Backbone) {
// Now we can reference not just Backbone but also jQuery and
// underscore since those two are dependencies for Backbone.
});

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

Fileupload is not working with RequireJS

I am having a problem when loading fileupload whilst using requirejs. The error that it gives me is:
TypeError: this._on is not a function
and I guess it is because fileupload requires jquery.ui.widget to be loaded too.
So I tried importing the lib, but I can't seem to make this right. Can anyone help me how to load it properly?
this is the code:
require.config({
paths: {
'jQuery': 'lib/jquery-1.10.2.min',
'jQuery-ui': 'lib/jquery-ui-1.10.3',
'jQuery-ui-widget' : 'jquery.ui.widget',
'bootstrap': 'lib/bootstrap.min',
'jquery-iframe': 'jquery.iframe-transport',
'fileupload': 'jquery.fileupload',
},
shim: {
'jQuery': {
exports: '$'
},
'jQuery-ui': {
deps: ['jQuery'],
exports: '$'
},
'jQuery-ui-widget': {
deps: ['jQuery', 'jQuery-ui-widget']
},
'bootstrap': {
deps: ['jQuery', 'jQuery-ui']
},
'fileupload': {
deps: ['jQuery', 'jQuery-ui', 'jquery-iframe']
}
},
// only for development purporses:
urlArgs: "bust=" + (new Date()).getTime()
});
require(['jQuery', 'jQuery-ui', 'bootstrap', 'layout', 'menu', 'modal', 'table', 'form', 'fileupload'], function ($, jqueryUi, _bootstrap, layout, menu, modal, table, form, fileupload) {
$(document).ready(function () {...
There are multiple problems with your configuration:
jQuery does not need a shim, and using a shim where none is needed can cause troubles.
jQuery hardcodes its module name as jquery (all lowercase) so you cannot refer to it under the name jQuery. Well, you could use a map config to map jQuery to jquery but you currently do not have such map in your configuration. I would recommend using jquery across the board, which is the current practice in just about every project I see that uses RequireJS and jQuery.
I also recommend using enforceDefine: true in your configuration so that RequireJS provides better diagnosis of module loading failures.

Jsjws JSON Web signatures and tokens

I'm trying to include jsjws in my current project (Backbone, Marionette) which uses RequireJS to include all modules. I have AMD and non AMD scripts included, the non AMD using shims but I'm not sure how jsjws (http://kjur.github.io/jsjws/) will work in this instance. Maybe someone can help?
Current RequireJS config with attempt at including jsjws:
paths: {
backbone: "vendor/backbone", "backbone.syphon":"vendor/backbone.syphon",
jquery: "vendor/jquery",
json2: "vendor/json2",
underscore: "vendor/underscore",
marionette: "vendor/backbone.marionette",
jsjws: "vendor/jws-3.0",
tpl: "vendor/tpl"
},
shim: {
underscore: {
exports: "_"
},
backbone: {
deps: ["jquery", "underscore", "json2"],
exports: "Backbone"
},
"backbone.syphon": ["backbone"],
marionette: {
deps: ["backbone"],
exports: "Marionette"
}
}
many thanks,
Wittner
Looking at the code for jsws and at the documentation, it seems to me that this is what you need to add to your shims:
jsjws: {
exports: "KJUR"
}
Or I believe you could have it export "KJUR.jws" to skip the top level namespace (which seems useless in this context).
I was not able to find a clear list of what dependencies it has. If I look at the various samples in the github repo, the list of files loaded before jsjws seems to vary quite a bit depending on the specific needs of the project. At any rate, whatever your project needs for jsjws to do its job would have to be added to a deps field, and probably these dependencies would get shims of their own.

Can I set a different path for a child dependency in the require.config?

I have two problems that are related to each other.
The first is that I want to have a folder named backbone, and that collides with having backbone as a short name for the library in the path. It seems that RequireJS thinks that backbone/model/User is a child of the backbone library or something. Solution, name the library Backbone with capital B.
The second problem is that I'm using ModelBinder, which has "backbone" as a dependency. Solution, change the minified file.
Both solutions seems like a bad hack for not doing something right in RequireJS configuration, but I cant figure out what I'm doing wrong.
My public folder structure is something like:
public/
js/
backbone/
model/
...
view/
...
vendor/
backbone.min.js
Backbone.ModelBinder.js
...
common.js
My common.js has something like this:
require.config({
baseUrl: "/js",
shim: {
'underscore': {
exports: '_'
},
"Backbone" : {
deps: ["underscore", "jquery"],
exports: 'Backbone'
}
},
paths: {
underscore: 'vendor/underscore.min',
jquery: 'vendor/jquery',
model_binder: 'vendor/Backbone.ModelBinder',
Backbone: 'vendor/backbone.min'
}
});
So my two questions are: How can I keep Backbone.ModelBinder as it is, and tell requirejs that when that library ask for backbone, its asking for js/vendor/backbone.min.js without "polluting" my global paths.
And why can't I use both backbone (lowercase b) in the path and have the directory?
One solution (yes, not so sane) is to include paths definitions for every directory under js/backbone, i.e.:
require.config({
...
paths: {
...
backbone: 'vendor/backbone.min', // NOTE lower-case 'b', as desired
"backbone/model": "backbone/model",
"backbone/view": "backbone/view",
... // and so on
}
});
This also means that there is no module directly under js/backbone.
An alternative would be to keep the capital 'B' in the module name for Backbone and use the map config for the Backbone.ModelBinder.js:
require.config({
...
paths: {
...
Backbone: 'vendor/backbone.min' // NOTE capital 'B' again
},
map: {
"model_binder": {
"backbone": "Backbone"
}
});
Thinkng retrospectively, the map can be applied to all modules so that whenever they request "backbone" (lower-case 'b') you deliver "Backbone":
require.config({
...
paths: {
...
Backbone: 'vendor/backbone.min' // NOTE capital 'B' again
},
map: {
"*": { // <------ Here difference form code above
"backbone": "Backbone"
}
});
Now anyone can ask for "backbone" and get Backbone, or "backbone/model/User" (or "backbone/module") and get the corresponding module.

Why is requirejs trying to append a '.js' to .jst template files that are loaded with the !text plugin?

I use a .jst extension for template files, and load these with the requirejs text! plugin. E.g.,
define([
'jquery',
'backbone',
'underscore',
'text!templates/MyView.jst'
],
function($, Backbone, _, templateText) {
return Backbone.View.extend({
template: _.template(templateText),
initialize: function() {
},
render: function() {
}
});
});
This works swell when I test locally. However, when I try to do this after I've deployed my static files to AWS (the dynamic portions of the app run on Heroku), it fails to load the .jst files and appears to be trying to append a .js to their url's.
For reference, here's my requirejs config (from main.js)
requirejs.config({
paths: {
//directories
plugins: "lib/plugins",
//libs
jquery: "lib/jquery/1.7.1/jquery",
underscore: "lib/underscore/1.3.3/underscore",
backbone: "lib/backbone/0.9.2/backbone",
moment: "lib/moment", // date lib
//require plugins
text: "lib/require/plugins/text",
domReady: "lib/require/plugins/domReady"
},
shim: { //specify all non-AMD javascript files here.
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
underscore: {
exports: '_'
},
moment: {
exports: 'moment'
},
'plugins/jquery.colorbox': ['jquery'],
'util/jquery.dropTree':['jquery'],
'util/common':['jquery']
}
});
I just updated the text.js README with info that explains this issue. It is basically a way to use text resources across domains, but it requires a build. There is a way to override. Details here:
https://github.com/requirejs/text#xhr-restrictions

Categories

Resources