Reputation: 18178
I'm new to RequireJS. I'm writing a number of custom bindings in Knockout.js and want to split them up using modules.
The layout of my code at the moment is:
/
default.html
js
code.js
require-config.js
lib
/require.js
bridge
bridge.js
bindings1.js
bindings2.js
bindings3.js
I want to load bridge.js from default.html and have that load in all of the bindings files. I've tried loading bridge.js using a or inline js using the require function.
My require-config is very simple:
require.config({
baseUrl: '/'
});
In bridge.js, I am having problems loading the files using a relative path. I tried:
require(['./bindings1', './bindings2', './bindings3'], function () {
console.log('loaded');
});
But this just ends up using the path baseUrl + 'bindings1.js', for example. I've tried various iterations in bridge.js. The only success I've had is if I write the entire path:
require(['js/bridge/bindings1', 'js/bridge/bindings2', 'js/bridge/bindings3'], function () {
console.log('loaded');
});
But that is not what I want. This seems like a pretty basic use case and I think I may be misunderstanding how the relative paths work.
Thanks
Upvotes: 33
Views: 29035
Reputation: 525
Use "packages" in require config. Here the valid answer for you question topic
require.config({
packages: [
{
name: 'packagename',
location: 'path/to/your/package/root', // default 'packagename'
main: 'scriptfileToLoad' // default 'main'
}]
... some other stuff ...
});
Inside of package you will be able to use relative paths.
Upvotes: 26
Reputation: 4996
Relative IDs are resolved relative to the module ID within which the ID is resolved. See AMD spec's module id format
section.
There are two ways to frame a relative dependency ID into a correct context/scope:
Define call is the start/definition of "module." All dependencies asked for within define()
call are scoped to be within/relative to that module's ID. Example:
// does not matter what the file name is.
define(
'hand/named/module'
, ['./child']
, factoryFunction
)
or
// inside of 'hand/named/module.js' file.
define(
['./child']
, factoryFunction
)
In both of the above cases, ./child
is resolved against the module ID defined by the define()
call. The module id in both cases is hand/named/module
and the ./child
is resolved to hand/named/child
(+ '.js' obviously, when time comes to get it)
You can change the scope of require
call from global to local by overriding it. You actually don't need to override / keep the name require
, it's the meaning of what it does changes. The require functionality becomes "local" to a particular module.
// inside 'hand/named/module.js' file
define(
['require']
, function(myLocalRequire){
require('./child', function(){
// outcome A
})
myLocalRequire('./child', function(){
// outcome B
})
}
)
There in outcome A you continue to use "global" require - the one attached to parent scope. Your ./child
resolves to baseURL + '/child'
The outcome B is locally-scoped, tied to module id hand/named/module
so, ./child
is resolved to hand/named/child
What @CristiPufu recommended is to override the global require
variable with local object that will be local only to the scope of that function:
// inside 'hand/named/module.js' file
define(
['require']
, function(require){
return function(){
// here we have access only to "local" require,
// since in the function declaration you decided to
// override the 'require' variable with new object.
// All code outside of this function will use global require.
require('./child', function(){
// outcome B
})
}
}
)
My preference is to put all relative resources inside define
call. Makes them explicit and meeningfull as it's clear what they are relative to.
Upvotes: 30