I am attempting to implement an EXTREMELY basic test that uses jquery, underscore.js and backbone.js loaded via require.js and for some reason I just cannot seem to get everything lined up properly. Research shows that others have not had these same problems so I know it must be something simple that I am just not seeing.
The problem I am having is that when backbone.js is loading, it cannot find a reference to _. I've found other people reporting the same issue but the problem was usually passing dependency references into handlers in the wrong order or other obvious problems. This is happening when backbone is loading.
I have also seen a number of 'mechanical' solutions such as 'put everything in the same file' and just loading them in a traditional way by having a number of script includes in the proper order but I REALLY want to get this working since it seems like such a powerful approach.
Initially I started with the structure here http://backbonetutorials.com/organizing-backbone-using-modules/ which works in the demo, but feels a little fragile because when I attempt to make very simple modifications or build up a simple sample from the ground up, it breaks.
After hitting my head against this for far too long, I went back and found this page Loading Backbone and Underscore using RequireJS with another simple example and I regained hope. However, after building up a new test based on it, I am STILL receiving the same issue even though the 0.5.3-optamd branch of backbone is supposed to handle its own dependency on underscore.
Without further ado, here is the super-straight-forward code that should work but instead is driving me insane. Here's hoping it's something obvious I just missed somehow:
index.html
<!DOCTYPE html>
<html>
<head>
<title>Backbone.js/Underscore.js via Require.js Learning Page</title>
<script src="js/libs/require/require.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<div>Backbone.js/Underscore.js via Require.js Learning Page</div>
<div class="testhook"></div>
</body>
</html>
js/main.js
require.config({
paths: {
'jquery': 'libs/jquery/1.7/jquery',
'underscore': 'libs/underscore/1.2.2/underscore',
'backbone': 'libs/backbone/0.5.3-optamd/backbone'
},
baseUrl: '/js',
urlArgs: 'v=1.0'
});
require([
'domReady',
'app'
],
function( domReady, App ){
domReady(function(){
console.log( 'Dom is ready' );
App.init();
});
}
);
js/app.js
// Filename: app.js
define([
'jquery',
'underscore',
'backbone'
],
function( $, _, Backbone ){
var init = function(){
console.log( 'app.js > init()' );
// jquery test (WORKS)
$('.testhook').append('testhook append');
// underscore test (WORKS)
console.log( _.map([1, 2, 3], function(n){ return n * 2; }));
// backbone test (DIES)
var artist = new Backbone.Model({
firstName: "Wassily",
lastName: "Kandinsky"
});
artist.set({birthday: "December 16, 1866"});
console.log(JSON.stringify(artist));
}
return { init: init };
}
);
The exact console output is:
Uncaught TypeError: Cannot call method 'extend' of undefined (backbone.js:150)
main.js:18 Dom is ready
app.js:11 app.js > init()
app.js:17 [2, 4, 6]
app.js:20 Uncaught TypeError: Cannot read property 'Model' of null (app.js:20)
NOTE:
Line 150 in unminified backbone.js is:
_.extend(Backbone.Model.prototype, Backbone.Events, {
I am on a Windows 7 machine using Chrome 17.0.938.0 dev-m.
My script versions are:
backbone: 0.5.3-optand
jquery: 1.7
require: 1.0.1
underscore: 1.2.2
My directory structure is:
js
+-- libs/
¦ +-- backbone/
¦ ¦ +-- 0.5.3-optamd/
¦ ¦ +-- backbone.js
¦ +-- jquery/
¦ ¦ +-- 1.7/
¦ ¦ +-- jquery.js
¦ +-- require/
¦ ¦ +-- require.js
¦ +-- underscore/
¦ +-- 1.2.2/
¦ +-- underscore.js
+-- app.js
+-- domReady.js
+-- main.js
+-- order.js
index.html
I cannot believe how much difficulty this is giving me and am really hoping someone can shed some light on what the heck is going on here.
I have actually spent a lot of time struggling with this same exact problem!
Here's how I have managed to get it working...
First off, download the new sample require-js project with jQuery 1.7. In the zip file you'll find a file called require-jquery.js which includes jQuery 1.7 which is now AMD compliant.
Then download the latest version of require, which is now also AMD, and last, try this version of Backbone...
https://github.com/jrburke/backbone/blob/optamd/backbone.js
Burke has created this off of a fork of backbone and made an AMD compliant version.
Then...
Index.htm
<!DOCTYPE html>
<html>
<head>
<title>Google Analytics API Browser</title>
<!-- This is a special version of jQuery with RequireJS built-in -->
<script data-main="main" src="require-jquery.js"></script>
</head>
<body>
</body>
</html>
main.js
require(['jquery','order!libs/underscore-min','order!libs/backbone','order!scripts/app'],
function($,_,Backbone,app){
app.init();
});
app.js
define(['jquery','backbone','scripts/home'], function($, Backbone, router){
var init = function(){
console.log("Started");
// In here you can load your routers/views/whatever
};
return { init: init};
});
My file structure looks like
/app/index.htm
/app/require-jquery.js
/app/order.js
/app/main.js
/app/text.js
/app/scripts/app.js
/app/scripts/home.js
/app/lib/underscore-min.js
/app/lib/backbone.js
Let me know if that helps, hit me up on twitter @jcreamer898 if you need some more help, I am literally working on the same stuff!
UPDATE I recently created a Github 2 github projects, one an actual app, and another just a simple starter...
https://github.com/jcreamer898/Savefavs
https://github.com/jcreamer898/RequireJS-Backbone-Starter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With