簡體   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