Client side I stub out paths to modules with SystemJS, like this
var systemJsConfig = {
baseURL: "./",
defaultJSExtensions: true,
map: {
'root-components': 'applicationRoot/rootComponents'
}
};
and so require('root-components/foo');
would map to applicationRoot/rootComponents/foo
.
The problem is, if I run a module with require('root-components/foo');
in Mocha, Node has no clue what that path means. Is there a sane way to accomplish this path mapping in Node?
Is Proxyquire capable of this? I read through their docs but found nothing to indicate it was.
This is just for unit testing, so I'm happy with any solution using any sort of their party utility.
If your only requirement is so simple you can make a utility function that overrides require
.
The new require applies a mapping to the path argument, looks for a module in the new path, and you can optionally fallback for modules that do not exist in the mapped path. The code should look like this
const oldRequire = require;
require = (path) => {
try {
const mapped = oldRequire(path.replace('root-components/foo', 'applicationRoot/rootComponents/foo'));
if (!mapped) {
throw new Error('module not found in mapped directory');
}
console.log('module resolved with mapping', path);
return mapped;
} catch (e) {
console.log('using old require without mapped path', path);
return oldRequire(path);
}
};
Option 1 - Modify NODE_PATH
(not recommended):
Modify NODE_PATH
to include the module path in the shell prior to launching node.js.
exports NODE_PATH=./path/to/module:$NODE_PATH
This is not a great option because it requires a pre-launch step and -- since the NODE_PATH
contains many paths -- it's not always clear where the module is being loaded from and there's the possibility of name collisions.
Option 2 - Move the module into an external repo
Lets say you move the components into a separate 'rootcomponents' repo available on your GitHub profile.
Then you can install it directly via:
npm install --save github:arackaf/rootcomponents
Then you should be able to map the project source to a System.js alias.
var systemJsConfig = {
baseURL: "./",
defaultJSExtensions: true,
map: {
'root-components': 'github:arackaf/rootcomponents'
}
};
From there it should work as you expected:
require('root-components/foo');
Option 3 - Load the module via relative path:
The config.map
option is only for mapping external dependencies to aliases.
One simple alternative is to provide a relative path. Relatives paths are based on the baseURL.
For instance, If you're attempting to load:
src/rootComponents/foo.js
The require would be:
require('./src/rootComponents/foo')
Note: This all assumes that the require()
statements are following System.js patterns/rules.
One other possible option is to provide a System.paths[]
option that creates an alias to a local path. I can't verify how/whether this'll work (ie I have never tried it) but the specifics can be found here
You could do module aliasing a lot of different ways as described in this gist, but the simpler way is just to set the starting root path with NODE_PATH
, and go from there:
Here's what it looks like with the NODE_PATH
environment variable:
NODE_PATH=./src node src/server/index.js
Then in all your files, no matter where they are in the hierarchy, will resolve from the ./src
directory. This eliminates the need for aliases like you describe, but I realize that in your case, may require moving/renaming many files.
Example: require('root-components/foo');
=> ./src/root-components/foo.js
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With