I have a Backbone app that gets errors of Backbone is not defined non-deterministically from different spots in my code that use Backbone. Sometimes it loads first and the site loads, other times it doesn't. I'm using the following as my main.js:
require.config({
paths: {
jqueryui: 'libs/jquery/jquery-ui',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-min',
text: 'libs/require/text',
order: 'libs/require/order',
searchcollector: 'libs/jquery/searchcollector.plugin',
guiders: 'libs/jquery/guiders'
},
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore'],
exports: 'Backbone'
}
}
});
require([
'views/app',
'helpers'
], function(app) {
var app = window.app = new app();
});
I'm using
<script data-main="/assets/js/main" src="/assets/js/libs/require/require-jquery.js"></script>
in my HTML so jQuery is loaded with the require. I took this advice from this (http://stackoverflow.com/questions/8131265/loading-backbone-and-underscore-using-requirejs) SO thread, but nothing seems to be working. Shouldn't the Shim be loading the Backbone first and then making it globally available? Any help appreciated.
Not sure if this is the correct answer but I've noticed that you don't list jquery as a Backbone dependency. While Backbone lists Underscore as the only hard dependency, Backbone.View will need jquery or zepto to work.
But why then, does it seem to work some of the time?
It might be that since jQuery is an AMD module, when you load, it sometimes loads first, and other times it doesn't. When it loads before Backbone, it is available and Backbone is happy. Otherwise, perhaps, the bad results you are getting.
Try something like this:
In your path add this:
jquery: 'libs/require/require-jquery'
And in your shim, add this:
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
Let me know what you get as a result. I've never used the shim feature of requirejs2.0 so I'm curious whether I'm understanding the deeper stuff correctly.
In my opinion it's a little bit hacky to load require and jquery in the same file.
And set jquery as a deps for Backbone is false because Underscore need jquery, and it's loaded before Backbone so the correct way is like this
require.config({
paths: {
'jquery': 'path to jquery'
,'underscore': 'path to underscore'
,'backbone': 'path to backbone'
**other paths...**
}
,shim: {
jquery: {
exports: '$'
}
,'underscore': {
deps: [ 'jquery' ]
,exports: '_'
}
,'backbone': {
deps: [ 'underscore' ]
,exports: 'Backbone'
}
}
});
Finally your tag script will be
<script data-main="/assets/js/main" src="/assets/js/libs/require.js">
</script>
Then you just have to call lib you need like this
define( [ 'jquery', 'underscore', 'backbone' ],
function( $, _, Backbone )
{
// stuff
} );
And for a model you maybe don't need jquery and underscore so just calling Backbone will work
define( [ 'backbone' ],
function( Backbone )
{
// Backbone.extend ?
} );
Related
I'm setting up a app with Require JS and backbone. But in my setup backbone is not loading correctly even if I included all the things
This is my main file.
require.config({
paths: {
/*app: 'app',*/
/*Libs and other resources*/
jquery: 'libs/jquery',
underscore: 'libs/underscore',
backbone: 'libs/backbone'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
}
}
});
require(['backbone'], function (Backbone) {
console.log(Backbone);
});
This is the status of the scripts.
UPDATE:
Removed the shim according to comments. But still its not working.
This happen due to a corrupted backbone.js lib files. I copied this file via a phpstorm from some other place in the project.
I have tried multiple suggestions and non of them are worked. At last I just created a single html file and tried to backbone worked there. Then I realized there may be a problem with backbone.js and just re-downloaded it and replaced. Now everything got to work.
I'd like to know how to load Underscore and Backbone using RequireJS and be able to configure Underscore before it's passed to Backbone.
I've seen this popular question on StackOverflow about this similar topic, but I haven't been able to figure out how to get Underscore to be configured for both of the following situations:
Underscore is required by itself
Underscore is loaded by Backbone
So my question is the following:
How can I configure Underscore using RequireJS when required by itself, and when required with Backbone in a module?
Here's what I've tried:
Approach that should work, but DOESN'T:
My first idea (as suggested here) was to define a requireJS module named (e.g.) rawUnderscore which returns Underscore without any configuration. Then, create a new module named underscore which requires rawUnderscore and configures it before returning its value. This causes loading problems (couldn't load backbone)
Configure Require.js modules
// When you initially setup require.js, add a new module to configure underscore
// Make it a dependency of backbone, so it'll always be loaded whenever
// backbone is used.
require.config({
paths: {
'underscore': 'underscoreConfig',
'rawUnderscore': 'underscoreOriginal'
},
shim: {
underscore: {
deps: ['rawUnderscore', 'jquery'],
exports: '_'
},
backbone: {
deps: ['underscore'],
exports: 'Backbone'
},
jquery: {
exports: 'jQuery'
}
}
});
underscoreConfig.js
define(['rawUnderscore'], function (_) {
'use strict';
_.templateSettings =
{
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%cleanHtml([\s\S]+?)%>/g,
escape : /<%[=-]([\s\S]+?)%>/g
};
return _;
});
Approach that works - Edit Underscore and remove AMD ability:
This works if I remove the AMD lines from Underscore.js (ie force Underscore to not be AMD compliant). I'd prefer not to do this as I like to keep libraries as they are, to ease future maintenance.
Configure Require.js to use the underscore patch
require.config({
shim: {
underscore: {
deps: ['underscorePatch'],
exports: '_',
init: function(patchIt){
return patchIt(this._);
}
}
}
});
underscorePatch.js
define('underscorePatch', [], function(){
'use strict';
function patch(_){
_.templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%cleanHtml([\s\S]+?)%>/g,
escape : /<%[=-]([\s\S]+?)%>/g
};
return _;
}
return patch;
});
Approach that works when loaded with Backbone:
This approach works, but only in the context of when Backbone being loaded as well. Not when Underscore is required by itself.
Configure Require.js modules
// When you initially setup require.js, add a new module to configure underscore
// Make it a dependency of backbone, so it'll always be loaded whenever
// backbone is used.
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscoreConfig', 'underscore', 'jquery'],
exports: 'Backbone'
},
jquery: {
exports: 'jQuery'
}
}
});
underscoreConfig.js
define(['underscore'], function (_) {
'use strict';
_.templateSettings =
{
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%cleanHtml([\s\S]+?)%>/g,
escape : /<%[=-]([\s\S]+?)%>/g
};
return _;
});
I think your first example was on the right track. The following seems to work:
main.js
requirejs.config({
paths: {
'underscore': 'underscoreConfig',
'originalUnderscore': 'underscore'
},
shim: {
'originalUnderscore': {
exports: '_'
}
}
});
underscoreConfig.js
define(['originalUnderscore'], function(_) {
_.templateSettings =
{
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%cleanHtml([\s\S]+?)%>/g,
escape : /<%[=-]([\s\S]+?)%>/g
};
return _;
});
My main.js look as below
requirejs.config({
//By default load any module IDs from ../js
baseUrl: '../js',
paths : {
'jquery': 'libs/jquery',
'underscore': 'libs/underscore',
'backbone': 'libs/backbone',
'bootstrap': 'libs/bootstrap'
},
shim: {
'jquery': {
exports: '$'
},
'backbone': {
//These script dependencies should be loaded before loading
//backbone.js
deps: ['jquery', 'underscore'],
//Once loaded, use the global 'Backbone' as the
//module value.
exports: 'Backbone'
},
'underscore': {
exports: '_'
},
'bootstrap': {
deps: ['jquery'],
exports: 'Bootstrap'
}
}
});
define(
['jquery', 'backbone','underscore', 'bootstrap'],
function (j, b, u, boot) {
console.log('jquery', j);
console.log('backbone', b);
console.log('underscore',u);
console.log('bootstrap', boot);
}
);
And my console image is like this:
When I click on X sign in alert, they disappear. So, I think bootstrap.js is loaded correctly. However, it says undefined in console. Can anyone make me clear is the bootstrap.js is loaded correctly and safe to use? And why it is saying undefined while rest of are defined well in console.
As jquery, backbone, and underscore export global variables to be used elsewhere, while bootstrap will just take the existing jquery object and will add plugins to the object, hence it won't export anything.
So, if you try to receive it in define callback, ideally it will be undefined. If you've used any bootstrap component on the page and if it is working it means bootstrap is integrated.
From the requirejs shim docs
For "modules" that are just jQuery or Backbone plugins that do not need to export any module value, the shim config can just be an array of dependencies:
requirejs.config({
shim: {
'bootstrap': ['jquery']
}
});
So, if you want, you can declare bootstrap like its specified in the docs.
Backbone doesn't get called in the indexview module.
using requirejs 2.1.5/2.1.4 and backbonejs 0.9.10
main.js after running r.js
...
// this is causing the backbone to return
// null/undefined in the next define call below
define("backbone", function(){});
define('views/index/IndexView', [
'underscore',
'backbone',
'text!templates/index/indexTemplate.html'
], function(_, Backbone, indexTemplate){
console.log(Backbone); // returns undefined
var IndexView = Backbone.View.extend({
...
BUT if I take out the first define call that registers backbone as a module, everything
works fine. but backbone-min.js gets loaded separately. but for now it's the only way
to make the script run. I am definitely missing something here.
main.js
require.config({
paths: {
underscore : 'libs/underscore/underscore-min',
backbone : 'libs/backbone/backbone-min'
templates : '../templates'
},
shim: {
'backbone': {
deps: ['jquery','underscore'],
exports: 'Backbone'
}
}
});
require(['app'], function(App){
App.initialize();
});
build.js
({
appDir: "../",
baseUrl: "js",
dir: "../../build",
optimize: "none",
paths: {
"jquery": "libs/requirejs/require-jquery",
"underscore" : 'libs/underscore/underscore-min',
"backbone": 'libs/backbone/backbone-min',
"templates": '../templates',
},
modules: [
{
name: "main",
exclude: ["jquery"]
}
]
})
I'm still getting my feet wet with backbone and requirejs.
any feedback is much appreciated.
First of all, you don't need that define('backbone',...). What is that part for anyways? You don't need to define Backbone as a module. Requirejs is doing the job of making Backbone available for you to use throughout your framework. As you can see in your code, by calling Backbone.View.extend(), Backbone already exists. If you want to inspect it, don't use console.log, use console.dir instead. In the chrome inspector it formats the output nicely.
Secondly, add underscore to the backbone deps array in your shim.
I've just had this issue, you need to add the 'shim' from your main.js to your build.js file, and will work like a charm ;)
I have defined a RequireJs configuration which defines paths and shims:
require.config({
// define application bootstrap
deps: ["main"],
// define library shortcuts
paths: {
app: "app"
, jquery: "lib/jquery"
, underscore: "lib/underscore"
, backbone: "lib/backbone"
, bootstrap: "lib/bootstrap"
},
// define library dependencies
shim: {
jquery: {
exports: "$"
},
underscore: {
exports: "_"
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
bootstrap: {
deps: ['jquery'],
exports: "bootstrap"
},
// main application
app: {
deps: ["backbone"],
exports: "App"
}
}
});
As you see the last "shim" declaration should make it able to access backbone (and it deps) when I load the main App(-namespace).
In reality this doesn't work:
require(["app"], function($, _, Backbone, App){
app.router = new Backbone.Router.extend({
// routing and route actions
});
});
What makes me wondering is that in the "backbone-boilderplate"-project, Backbone (and its deps) are available this way:
https://github.com/tbranyen/backbone-boilerplate/blob/master/app/main.js
The not even had to define this in the function.
So what am I doing wrong?
From what I've read, requirejs passes arguments based on what you specify in the array... Thus your call should look like this:
require(["app"], function (App) { // less arguments
});
Or like this:
require(
["jquery", "underscore", "backbone", "app"], // more deps
function ($, _, Backbone, App) {
}
);
Remove the $, _, Backbone-parameters from the require-function where you extend the Router. The shims export global values, so there is no need to reference to them in require or define calls like you do for regular dependencies.
Passing them as parameters messes with the global variables and most likely results in them being undefined.