Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RequireJS relative paths

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

like image 449
Szymon Rozga Avatar asked Jan 27 '13 14:01

Szymon Rozga


People also ask

Is RequireJS still relevant?

RequireJS has been a hugely influential and important tool in the JavaScript world. It's still used in many solid, well-written projects today.

What is the main purpose of the RequireJS framework?

RequireJS is a JavaScript file and module loader. It improves perceived page load times because it allows JavaScript to load in the background. In particular, it enables asynchronous JavaScript loading.

What is a RequireJS module?

RequireJS loads each dependency as a script tag, using head. appendChild(). RequireJS waits for all dependencies to load, figures out the right order in which to call the functions that define the modules, then calls the module definition functions once the dependencies for those functions have been called.

What is Shim RequireJS?

As per RequireJS API documentation, shim lets you. Configure the dependencies, exports, and custom initialization for older, traditional "browser globals" scripts that do not use define() to declare the dependencies and set a module value. - Configuring dependencies.


1 Answers

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

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)

"Scoped" require

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.

like image 73
ddotsenko Avatar answered Sep 28 '22 06:09

ddotsenko