Reputation: 8656
I am using RequireJS and I have hundreds of modules. I would like every single module to have a base set of modules already defined and ready to go, without having to list them all in every single module.
I would like to define a single, global module that every script uses, which returns jQuery and includes bunch of other stuff we need, like the jQuery validator plugin, among others.
Here is a simplified version of my layout.
js/app/Config.js
js/app/Global.js
js/app/util1.js
js/app/util2.js
js/app/foo.js
js/vendor/require.js
js/vendor/jquery.min.js
js/vendor/jquery.validator.js
<script src="/js/app/Config.js"></script>
<script src="/js/vendor/require.js"></script>
<script>
require('app/foo');
</script>
var require = {
baseUrl : '/js',
paths : {
'global' : 'app/Global',
'jquery' : [ 'vendor/jquery.min' ],
'jquery.form' : 'vendor/jquery.form',
'jquery.validate' : 'app/_config/jquery.validate.custom',
'jquery.validate.core' : 'vendor/jquery.validate',
'jqueryui' : 'vendor/jquery-ui-1.10.4.custom.min',
'underscore' : 'vendor/underscore'
},
shim : {
'jquery.validate' : [ 'jquery.form', 'jquery.validate.core' ],
'jquery.validate.core' : [ 'jquery' ],
'underscore' : {
exports : '_'
}
};
define([
'jquery',
'app/util1',
'app/util2'
], function ($) {
// all my custom global functions and code go here
return $;
});
define([
'global'
], function ($) {
'use strict';
$('#foo').validate(); // $ is undefined here
});
I assumed this would work, but it says that $ is undefined in foo.js. Shouldn't the 'foo' module load Global, which must load all the modules it has in the require array, like 'util1' and 'util2'?
Upvotes: 0
Views: 94
Reputation: 1357
Try installing xrayquire and then in the console debugger check for circular dependencies with xrayquire.showCycles();
.
Regarding your question, I had a similar problem, where I found myself writing loads of require files but I kept getting dependency loading errors thrown by requirejs. This may seem overkill, but my solution was to create interfaces (not the class type, but my own global library).
So let's say I have a folder called [menu] with loads of require files, with the following directory structure:
[app]
interfaces.js
[comms]
IComms.js
connect.js
[menu]
IMenu.js
create.js
[listener]
onClick.js
other files...
For each top-level directory, I create an interface file e.g. IMenu.js
, this is the ONLY way I can invoke methods, by using this interface file. So if I'm in the comms
directory, I can invoke a method with myapp.menu.create();
without worrying about circular dependency nor loading other require files.
IMenu.js
define(function(require) {
var create = require('./create');
var onClick = require('./listener/onClick');
// load many other files here...
function func() { 'this is private' };
// exports
return {
'create' : function() { create(); },
'onClick' : function(e) { return onClick(e); }
};
});
interfaces.js
define(function(require) {
function setLocations() {
window.myapp = {
'comms' : require('comms/IComms'),
'menu' : require('menu/IMenu'),
// load other app interface files...
};
};
// exports
return function(callback) {
setLocations();
callback();
};
});
main.js
require.config({
'paths' : {
jquery : '../libs/jquery',
blah...
}
});
// entry point
require(['interfaces'], function(interfaces) {
interfaces(function() {
// global `myapp` now fully loaded with interface files
myapp.comms.connect();
myapp.menu.create();
});
});
Summary
In main.js
, I call the interfaces file and then invoke each interface to build the app. Since it passes a callback, once it's done I can call any interface knowing that it exists on the global `myapp' variable.
It's a dirty hack but I get zero errors when I use xray and it allows me to encapsulate my whole code-base behind simple invocation, e.g. myapp.comms.addUser(), myapp.comms.disconnect(), myapp.menu.create() etc..
Upvotes: 1