r42
Mix in node's require, some angular dependency injection look&feel and the ease of use of RequireJS and what do you get?
Dependency injection done right for Node.js!
WARNING
This library is now in 0.2.0 version. It means it is rather stable (and is actually working properly on a big project with well over 100 modules). But right now, the API is still being worked out to be as great as possible. It might change with time but it will stay stable over minor versions (0.1.x). Be carefull to the documentation when upgrading to >=0.3.
TODO
Testing API to be able to load mockups to replace a specific module.
Getting started
Installation
npm install r42
Your first module
Let's code lib/toto.js
:
define(function (path, fs, _, dep1, dep2) {
return ;
});
Configuring & lauching your project
var r42 = require('r42');
var path = require('path');
r42.config({
baseDir: path.join(__dirname, 'lib'),
paths: {
_: 'lodash',
library: '../vendor/library',
sub: '../sub',
shMod: 'sh/module',
sh: 'shortcut',
shMod2: 'sh/module2',
},
});
r42.inject(function (toto) {
});
More complex dependencies
Module in subfolders
If you want to resolve complex names in subdirectories, you can use the optional replacer
argument of the define function. Here is an example:
define({
test: 'sub/folder/test',
}, function (test) {
});
The object maps an argument's name to the real module name locally. The argument name will be replaced by the given module name before injection happens.
You can also use special r42 comments (looking like /*! module */
) before your argument names:
define(function ( test) {
});
Note : spaces are optional in r42 comments.
Modules in the same folder
Sometimes, it is a pain to refer to a module in the same folder as you are right now. r42 allows for a fine way to do so.
Using $
to prefix your variable's name will automatically cause r42 to replace it by your current module's "path". It also works to prefix files in the replacer
object.
In a module module/toto.js
:
define({
superSub: '$super/sub',
}, function (superSub, $sideFn, sideVal) {
});
Special case : index.js in a subfolder
You can refer to an index module using only the folder's name just like so:
In file folder/index.js
:
define(function () {
return {
answer: 42
};
});
And in a file at the same level as folder:
define(function ($folder) {
});
Circular dependencies
Those are working "automatically" but you NEED to exports barebone objects on both modules for it to work.
Here is an example:
In a module a.js
:
define(function (b) {
return {
aFn: function () {
b.bFn();
},
};
});
In a module b.js
:
define(function (a) {
return {
bFn: function () {
a.bFn();
},
};
});
Special APIs
Loading modules dynamically
You can also use r42.inject to load modules dynamically. In this case, provide a module name or module list and optionally a replacer
as usual. Here is what it could look like:
In module dynamic.js
define(function (r42) {
var _ = r42.inject('lodash');
var alias = r42.inject({ alias: 'lodash' }, 'alias');
var modules = r42.inject(['util', 'net']);
modules = r42.inject({a: 'util', b: 'net'}, ['a', 'b']);
});
Printing dependencies
This function might be useful to gather information about your module & to debug dependencies problems. It takes an options
parameter which is an object that can take the following two options:
colors
(defaults to true
): whether to colorize the output or notprint
(defaults to true
): whether to print to stdout automatically the result or not
WARNING: The colors
option requires that you install chalk
(version >=0.4.0) as a dependency of your project.
It returns a string containing the dependencies information.
var r42 = require('r42');
r42.config({
});
r42.inject(function () {
r42.dumpDeps();
var depstr = r42.dumpDeps({
colors: false,
print: false,
});
});
Using r42 in libraries
Since version 0.0.21, r42 has been rewritten to be completely synchronous. This means that you can use it easily, even to create library packages. Here is a simple example of what your main library file might look like :
var r42 = require('r42');
r42.config();
r42.inject(function () {
module.exports = {
};
});