I'm trying to create a require wrapper to load dependencies, but I found one thing difficult to make it works as the original require function. When the path is a relative one, the wrapper cannot resolve to the correct one since my loader and the caller files are not in a same folder. Here is a simplified description.
index.js
lib/
loader.js
foo/
bar.js
baz.js
index.js
var loader = require('./lib/loader.js'),
bar = require('./foo/bar.js');
bar(loader);
lib/loader.js
module.exports = function (path) {
return require(path);
};
foo/bar.js
module.exports = function(loader) {
var baz = loader('./baz.js');
console.log(baz);
};
foo/baz.js
module.exports = 'baz';
Obviously, when the index.js is executed, baz.js file cannot be found. Is there any way to resolve to the correct file?
I've found a relative solution but it's not working.
You can use module.require
to call require
from another module's context, so you could do this by passing that context into the loader
method:
lib/loader.js
module.exports = function (moduleContext, path) {
return moduleContext.require(path);
};
foo/bar.js
module.exports = function(loader) {
var baz = loader(module, './baz.js');
console.log(baz);
}
I agree with @JohnnyHK that passing the module
context is a cool solution, but I still want to keep the calls simple. Finally I understand the answer I mentioned, and I get what I want.
loader.js
var getCaller, path;
path = require('path');
getCaller = function() {
var stack, traceFn;
traceFn = Error.prepareStackTrace;
Error.prepareStackTrace = function(err, stack) {
return stack;
};
stack = (new Error()).stack;
Error.prepareStackTrace = traceFn;
return stack[2].getFileName();
};
module.exports = function(file) {
var base;
base = path.dirname(getCaller());
return require(path.resolve(base, file));
};
The getCaller
function use error trace stack to get the filename of the caller of it's caller. I know it's a very tricky approach, and I don't recommend it as a common solution since its compatibility to different versions of Node.js has not been tested.
This loader is used for preparing dependencies, so it doesn't need to iterate node_modules folders. The only two cases are relative path and absolute path, and they can all be correctly processed by this loader.
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