requirejs + backbonejs + optimizer = backbone undefined - backbone.js

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 ;)

Related

Backbone is not defined even its loaded with RequreJS

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.

BackboneJS How to include MomentJS <locale> feature

I want to include the locale-feature from MomentJS into one of my Backbone Views. http://momentjs.com/docs/#/i18n/adding-locale/ - but I get an error:
Uncaught TypeError: undefined is not a function - and it refers to:
return moment.defineLocale('da', {
In my config.js I have:
require.config({
deps: ['main'],
paths: {
jquery : '../lib/jquery-2.1.1.min',
underscore : '../lib/lodash-2.4.1',
backbone : '../lib/backbone',
moment : '../lib/moment.min',
locale : '../lib/locale/da'
},
And in my View I have:
define([
'app',
'backbone',
'moment',
'locale'
],
function (App, Backbone, moment, locale) {
...
Does anyone know what the issue could be?
Here is the oficial documentation http://momentjs.com/docs/#/use-it/require-js/
seems to me that there is a little trick to work with requirejs

Loading Dynamic Require.js modules

Have spent the whole day on this and i think its time for a shout out. I am using require.js to include modules in my backbone app. This is what i have:
My requirejs config:
paths:
jquery: "backbone/initializers/jquery_loader"
jqueryui: "backbone/initializers/jqueryui_loader"
modules:
- name: 'application'
- name: 'jquery'
exclude: ['application']
- name: 'jqueryui'
exclude: ['application', 'jquery']
- name: 'email'
exclude: ['application']
- name: 'department_home'
exclude: ['application']
priority: ['application', 'jquery', 'jqueryui']
My jquery_loader:
define ["jquery.min"], () ->
jQuery = $
jQuery.noConflict(true)
My jqueryui_loader:
define ['jquery.ui.all'], () ->
My email module:
define ['marionette', 'jqueryui', 'tags'], (Marionette, ui, tags) ->
My department home module
define ['marionette', 'jqueryui', 'dept_tags'], (Marionette, ui, tags) ->
Everything works as expected and compiles, but maybe i don't understand it or i am missing something, the email module is loaded dynamically on a click event, and it has jqueryui included in it, which i believe is just an r.js optimized file.
Now i do another click event after email module is loaded, and i see that the department module also has jquerui in it, both come in at 90KB, what i expected is for department module to use the jqueryui thats already loaded by the email module.
Appreciate your help!
I think you shouldn't use jquery loader like this. You should use the shim property to initialize the noConflict. I've answered something similar a few days ago.
In your case it would be something like this (but in coffeescript then):
require.config({
paths: {
jquery: "path/to/jquery",
jqueryui: "path/to/jqueryui"
},
shim: {
jquery: {
exports: 'jQuery',
init: function() {
return this.jQuery.noConflict();
},
jqueryui: {
deps: ['jquery']
}
}
});

Backbone Not Defined

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 ?
} );

Requirejs2: How to handle own files?

I have configured requirejs to load the core libs (jquery, underscore, backbone).
Now I would like to add my backbone models, controllers, views, etc to be loaded asyncronly
I found a lots of tutorials to this topic and lots of "ready" boilerplates unfortunatly I mentioned that most approaches are depreceated or rather complicated (even there are better approaches).
One example is how I configured requirejs for the main libs:
https://stackoverflow.com/a/10914666/1309847
So how do I load Backbone Views, Models, Collections, Routers, Controllers and Templates with a simple and valid Requirejs configuration?
I followed youre advice but get some strange error
main.js
require.config({
paths: {
jquery: 'vendors/jquery/jquery',
underscore: 'vendors/underscore/underscore',
backbone: 'vendors/backbone/backbone'
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
require(['app'], function(app){
});
app.js
define(['jquery', 'underscore', 'backbone'], function($, _, Backbone){
var Message = new Backbone.Model.extend({
//idAttribute: '_id',
//defaults: { body: '' }
//url: function(){ return this.id ? '/messages/' + this.id : '/messages'; }
});
var newMessage = new Message({ body: 'hi' });
newMessage.save();
});
The error occours in app.js:
Uncaught TypeError: Object [object Object] has no method 'apply'
When I comment the new Backbone.Model.extend part I don't get any error anymore.
in my experience, the best way to bootstrap your application is by creating a Backbone.Router. So you can associate urls with your application functionality.
If you are using RequireJS+Backbone, you probably have a main.js where RequireJS is configured (paths, shims, etc). The first call to "require" is used to load a initial script in order to bootstrap the whole app.
For example:
/**
* main.js - RequireJS bootstrap
*/
require.config({
paths: {
//your paths
},
shim: {
//your shims
}
});
require(
[
'app' //app.js is at the same directory as main.js
],
function(app) {
app.init();
}
);
then in app.js you can create a new Router instance, or you can just start creating Views and Models.
For further reference: http://addyosmani.github.com/backbone-fundamentals/
So as I have now understood right: You have to wrap a requirejs function around youre own custom js file.
The function is called define. The first parameter is an array of the dependencies which you have defined in the main.js file or a relative path to another custom js from you.
The second parameter is the callback which holds the original file. Important is that you return the object, function, array or variable which you want to share.
The whole thing looks like this:
define(
['underscore', 'backbone'], // the dependencies (either relative paths or shortcuts defined in main.js
function(_, Backbone){ // the return statement of the deps mapped to a var
var MessageModel = Backbone.Model.extend({ // the original code, file
defaults: { body: '' },
initialize: function(){}
});
return MessageModel; // the return statement, sharing the "final result", sometimes you return the initialize parameter
});
The same for a collection wrapping the models:
define(
['jquery', 'underscore', 'backbone', 'models/message_model'], // deps and the last one is the relative path
function($, _, Backbone,MessageModel){ // same as above explained
var MessageCollection = Backbone.Collection.extend({
model: MessageModel,
initialize: function(){}
});
return MessageCollection;
});
I now only have to figure out how I can bootstrap to whole application. But I think I need more knowledge of backbone to do this :)

Resources