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']
}
}
});
Related
I am trying to use angular NG6 starter. in its source code, import angular from angular is written almost every js file. So I try this:
new webpack.ProvidePlugin({
// $: "jquery",
// jQuery: "jquery",
// "window.jQuery": "jquery",
'angular': 'angular',
}),
But it can not work. I dont know why, and how to solve this issue.
Here the solution to the first error message in your screenshot "angular.module is not a function": Angular 1 is not working nicely with webpack without a shim (see https://github.com/webpack/webpack/issues/2049). Try this webpack loader config:
module: {
loaders: [
/*
* Necessary to be able to use angular 1 with webpack as explained in https://github.com/webpack/webpack/issues/2049
*/
{
test: require.resolve('angular'),
loader: 'exports?window.angular'
},
]
},
plugins: [
new webpack.ProvidePlugin({
'angular': 'angular',
}),
],
This should initialize the angular object properly instead of the default action of setting it to an empty object (which does not have a property named module).
U need to use sth like this:
var app = angular.module('RequiredName', ['ui.router','ui.bootstrap']);
and use this on app file and call your app module like in the parts of project that u are going to use any function or method implemented in your app.js file in app.factory or app.controller or...
I'm using Typescript 1.7, AngularJS 1.5.7, oclazyload 1.0.9, ui-grid 3.2.5, ui-router 0.3.1, requirejs 2.2.0
First, everything was working fine until I upgraded from Angular 1.4.3 to 1.5.7
In my code I pull in source like so from the require config:
shim: {
'angular': {
exports: 'angular',
deps: ['Scripts/RequireJS/V.2.2.0/domReady!']
},
'ngSanitize': {
deps: ['angular']
},
'ngAnimate': {
deps: ['angular']
},
'ngTouch': {
deps: ['angular']
},
'uiRouter': {
deps: ['angular', 'ocLazyLoad']
},
'uiBootstrapTpls': {
deps: ['angular']
},
'ocLazyLoad': {
deps: ['angular', 'ngAnimate']
},
Once the require calls complete I config angular and then call bootstrap manually.
the user comes to a login page, logs in, then goes to the homepage. The homepage has a ui-grid, so we lazy load ( oc lazy loader ) on the state change like so:
$ocLazyLoad.load('uiGrid');
note uiGrid was configured in the angular module config call like this:
$ocLazyLoadProvider.config({
events: true,
jsLoader: requirejs,
serie: true,
modules: [
{
name: 'uiGrid',
files: ['Scripts/AngularUIGrid/V.3.2.5/ui-grid.min']
}
Now this all works just fine using Angular 1.5.7, but if I reload the page I get this:
TypeError: $$animateJs is not a function\n
at prepareAnimation (http://myServer/Scripts/Angular/V.1.5.7/angular-animate.js?bust=2016_6_12_12_24:2152:14)\n
at initDriverFn (http://myServer/Scripts/Angular/V.1.5.7/angular-animate.js?bust=2016_6_12_12_24:2136:16)\n
at invokeFirstDriver (http://myServer/Scripts/Angular/V.1.5.7/angular-animate.js?bust=2016_6_12_12_24:3234:24)\n
at Array.triggerAnimationStart (http://myServer/Scripts/Angular/V.1.5.7/angular-animate.js?bust=2016_6_12_12_24:3080:33)\n
at nextTick (http://myServer/Scripts/Angular/V.1.5.7/angular-animate.js?bust=2016_6_12_12_24:423:15)\n
at scheduler (http://myServer/Scripts/Angular/V.1.5.7/angular-animate.js?bust=2016_6_12_12_24:393:5)\n
at Array.<anonymous> (http://myServer/Scripts/Angular/V.1.5.7/angular-animate.js?bust=2016_6_12_12_24:3102:9)\n
at Scope.$digest (http://myServer/Scripts/Angular/V.1.5.7/angular.js?bust=2016_6_12_12_24:17338:55)\n
at Scope.$apply (http://myServer/Scripts/Angular/V.1.5.7/angular.js?bust=2016_6_12_12_24:17553:24)\n
at done (http://myServer/Scripts/Angular/V.1.5.7/angular.js?bust=2016_6_12_12_24:11698:47)
This didn't happen with 1.4.3 Angular.
A cursory lookindicated to me that when this happens it is because in angular-animate.js the DI of $$animateJs is undefined...therefore the displayed error message
var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) {
$$animationProvider.drivers.push('$$animateJsDriver');
this.$get = ['$$animateJs', '$$AnimateRunner', function ($$animateJs, $$AnimateRunner) {
Is oclazyload the problem, I looked at it a little bit and didn't know if maybe the way it decorates bootstrap and module could contribute?
Thanks in advance for any help.
The ui.grid has dependencies on ngAnimate so you need to load it in before loading ui.grid.
resolve: helper.resolveFor('ngAnimate','ui.grid')
Hope this helps.
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.
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 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 ?
} );