繁体   English   中英

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

[英]Wrap require in Node.js which can resolve relative path call

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

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);
};

富/ bar.js

module.exports = function(loader) {
  var baz = loader('./baz.js');
  console.log(baz);
};

富/ baz.js

module.exports = 'baz';

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

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

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

LIB / loader.js

module.exports = function (moduleContext, path) {
  return moduleContext.require(path);
};

富/ bar.js

module.exports = function(loader) {
  var baz = loader(module, './baz.js');
  console.log(baz);
}

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

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));
};

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

注意

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

使用__dirname

__dirname可能就是你需要的。 您可以使用它将相对路径转换为绝对路径,该路径将与require

var resolve = require('path').resolve;

var relativePathToModule = './a/b/c';

// resolve is not strictly necessary, but it does clean up the path for you.
var absolutePathToModule = resolve(__dirname + relativePathToModule);

您可以在任何模块中将absolutePathToModule传递给require,它将始终找到正确的模块。

请注意, __dirname是使用它的模块的目录的绝对路径。

使用require.resolve

或者,您可以使用require机器本身为您解析模块:

var relativePathToModule = './a/b/c';

var absolutePathToModule = require.resolve(relativePathToModule);

这样可以在没有模块可以解析时抛出,并省略__dirname

注意

这些并不是你想要的,但是接近require解析路径的方式。 require__dirname属于它们所使用的模块,所以其他任何东西都意味着传递模块的上下文以在另一个模块中使用上述机制(参见JohnnyHK的答案)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM