Did anyone successfully loaded moment.js in a r.js build (with almond) ?
I am using backgrid and backgridMomentCell: everything's works perfectly before I build my main.min.js file. After build time moment is not defined and thus can't be found by backgridMomentCell extension.
I've tried several option (even shim) without success.
If somedoby has a require.config that work can he/she shares it ?
EDIT (sorry for not answering any sooner, launch time kept me away from SO):
In the build file BackGridMomentCell keep throwing "moment is not defined" errors.
My code as requested in the comment
requirejs.config({
paths: {
backbone: 'vendor/backbone-1.1.0',
backbonePageable: 'vendor/backbone-pageable-1.4.1',
backgrid: 'vendor/backgrid/js/backgrid-0.2.6',
backgridPaginator: 'vendor/backgrid/js/extensions/paginator/backgrid-paginator',
backgridMomentCell: 'vendor/backgrid/js/extensions/moment-cell/backgrid-moment-cell',
bootstrap: 'vendor/bootstrap/js/bootstrap-3.0.1',
bootstrapDatepicker: 'vendor/bootstrap-datepicker/bootstrap-datepicker-fda46bb',
codemirror: 'vendor/codemirror/js/codemirror-3.20',
codemirrorMarkdown: 'vendor/codemirror/mode/markdown/markdown',
jsDiff: 'vendor/diff-1.0.7',
fullCalendar: 'vendor/fullcalendar/fullcalendar-1.6.4',
fullCalendarJqueryUiCustom: 'vendor/fullcalendar/jquery-ui-1.10.3.custom.min',
jquery: 'vendor/jquery-1.10.2',
marked: 'vendor/marked-0.2.10',
select2: 'vendor/select2/select2-3.4.5',
speakingurl: 'vendor/speakingurl-0.4.0',
underscore: 'vendor/underscore-1.5.2',
moment: 'vendor/moment.with.langs'
},
shim: {
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
backgrid: {
deps: ['jquery', 'backbone', 'underscore'],
exports: 'Backgrid'
},
backgridPaginator: {
deps: ['backgrid']
},
backgridMomentCell: {
deps: ['backgrid','moment']
},
bootstrap: {
deps: ['jquery']
},
bootstrapDatepicker: {
deps: ['jquery']
},
codemirror: {
exports: 'CodeMirror'
},
codemirrorMarkdown: {
deps: ['codemirror'],
exports: 'codemirrorMarkdown'
},
fullCalendar: {
deps: ['jquery', 'fullCalendarJqueryUiCustom']
},
fullCalendarJqueryUiCustom: {
deps: ['jquery']
},
select2: {
deps: ['jquery']
},
underscore: {
exports: '_'
}
}
});
The head of my module
define([
'jquery',
'fullCalendar',
'underscore',
'backgrid',
'backgridPaginator',
'moment',
'backgridMomentCell',
'backbone',
'collections/ItemPaginatedCollection',
'utils/BackgridCustomUriCell'
], function ($, _fullCalendar, _, Backgrid, _backgridPaginator, moment, MomentCell,Backbone, ItemPaginatedCollection, BackgridCustomUriCell) {
"use strict";
....
EDIT 3 :
Loading moment.js before my compiled main.js works but is not optimal IMHO.
The easiest two methods I have found:
1) Wrap backgrid-moment-cell.js in the CommonJS wrapper code specified in the RequireJS API. You can do this dynamically during the build process using the conversion tool mentioned in the API.
2) Require moment-cell inline and set findNestedDependencies to false in your build.js.
The issue is that the moment-cell code passes in this to itself when it is initialized, and looks for either "exports.moment" or "this.moment."
On a related note, including moment in the shim for moment-cell is unnecessary, and technically you should include underscore. From the API:
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.
Moment is actually an AMD module.
Most likely your problem is that you didn't specify findNestedDependencies true in your build file.
Take a look at this commit (from my book on RquireJS and Backbone.Marionette): https://github.com/davidsulc/structuring-backbone-with-requirejs-and-marionette/commit/85d3d3dd40d0cebd858224c3903a12d6998d668d
I think it's to do with moment's global object being deprecated.
2.4.0 - Deprecate globally exported moment, will be removed in next major
https://github.com/moment/moment
Moment needs to be defined in the specific module now.
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 _;
});
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.
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.
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 ?
} );