在Node.js中包裹需要可以解析相对路径调用

Rix*_*Rix 3 javascript node.js

我正在尝试创建一个require包装器来加载依赖项,但我发现有一件事很难让它作为原始的require函数.当路径是相对路径时,包装器无法解析为正确的路径,因为我的加载器和调用者文件不在同一个文件夹中.这是一个简化的描述.

index.js
lib/
  loader.js
foo/
  bar.js
  baz.js
Run Code Online (Sandbox Code Playgroud)

index.js

var loader = require('./lib/loader.js'),
    bar = require('./foo/bar.js');
bar(loader);
Run Code Online (Sandbox Code Playgroud)

LIB/loader.js

module.exports = function (path) {
  return require(path);
};
Run Code Online (Sandbox Code Playgroud)

富/ bar.js

module.exports = function(loader) {
  var baz = loader('./baz.js');
  console.log(baz);
};
Run Code Online (Sandbox Code Playgroud)

富/ baz.js

module.exports = 'baz';
Run Code Online (Sandbox Code Playgroud)

显然,当执行index.js时,找不到baz.js文件.有没有办法解决到正确的文件?

我找到了一个相对的解决方案,但它没有用.

Joh*_*yHK 5

您可以使用从另一个模块的上下文module.require调用require,因此您可以通过将该上下文传递给loader方法来完成此操作:

LIB/loader.js

module.exports = function (moduleContext, path) {
  return moduleContext.require(path);
};
Run Code Online (Sandbox Code Playgroud)

富/ bar.js

module.exports = function(loader) {
  var baz = loader(module, './baz.js');
  console.log(baz);
}
Run Code Online (Sandbox Code Playgroud)


Rix*_*Rix 4

我同意@JohnnyHK 的观点,即传递上下文module是一个很酷的解决方案,但我仍然希望保持调用简单。最后我明白了我提到的答案,我得到了我想要的。

加载器.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));
};
Run Code Online (Sandbox Code Playgroud)

getCaller函数使用错误跟踪堆栈来获取其调用者的调用者的文件名。我知道这是一种非常棘手的方法,并且我不推荐将其作为通用解决方案,因为它与不同版本的 Node.js 的兼容性尚未经过测试。

笔记

该加载器用于准备依赖项,因此不需要迭代node_modules文件夹。唯一的两种情况是相对路径和绝对路径,它们都可以被这个加载器正确处理。