I'm following Uzi Kilon's BackboneJS / RequireJS / backbone.LocalStorage example at http://kilon.org/blog/2012/08/build-backbone-apps-using-requirejs/.
When I git clone https://github.com/uzikilon/Todos
it works just fine - but it uses older versions of backbone.localstorage. If I replace lib/backbone.localStorage
with the newer version http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.1.0/backbone.localStorage-min
, though, then I get "Uncaught TypeError: undefined is not a function" here: https://github.com/uzikilon/Todos/blob/master/js/models/Todo.js#L3 - why? I think this has something to do with the tricky details at http://requirejs.org/docs/api.html#config-shim or perhaps this: http://blog.mostlystatic.com/2013/01/backbone-localstorage-uncaught.html.
require.config({
baseUrl: "./js/",
paths: {
jquery: 'lib/jquery-1.8.2',
underscore: 'lib/underscore-1.4.2',
backbone: 'lib/backbone-0.9.2',
// 'backbone.localStorage': 'lib/backbone.localStorage'
'backbone.localStorage': 'http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.1.0/backbone.localStorage-min'
},
shim: {
underscore: {
exports: "_"
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'backbone.localStorage': {
deps: ['backbone'],
exports: 'Backbone'
}
}
});
The problem lies with the fact that the latest Backbone localStorage is AMD compatible, where as the version in that example is not, hence the shim config.
The fix
Remove the shim
config for backbone.localStorage, you won't be needing it:
'backbone.localStorage': {
deps: ['backbone'],
exports: 'Backbone'
}
Then, in Todo.js
change the define call from:
define(['underscore', 'backbone.localStorage'], function(_, Backbone) {
to:
define(['underscore', 'backbone', 'backbone.localStorage'], function(_, Backbone) {
Why?
The shim exports
config was being used to say 'When I ask for backbone.localStorage, return me Backbone'.
This allowed 'backbone.localStorage' to be used simply as Backbone inside the Todo module.
But now backbone.localStorage
supports AMD and explicitly returns a value from the define
call. So the value of Backbone
in Todo.js is no longer the Backbone library, but is actually a constructor for Backbone.LocalStorage
As far as I understand, the shim
config is ignored for AMD modules, or at least should not be used:
Only use other "shim" modules as dependencies for shimmed scripts, or
AMD libraries that have no dependencies and call define() after they
also create a global (like jQuery or lodash). Otherwise, if you use an
AMD module as a dependency for a shim config module, after a build,
that AMD module may not be evaluated until after the shimmed code in
the build executes, and an error will occur. The ultimate fix is to
upgrade all the shimmed code to have optional AMD define() calls.
To fix things up the additional dependency needs to be added in Todo.js so that so that the callback parameters match up.
Hopefully that makes sense.