Node.js 需要一个相对于包根目录的文件

Posted

技术标签:

【中文标题】Node.js 需要一个相对于包根目录的文件【英文标题】:Node.js require a file relative to the root of the package 【发布时间】:2021-05-31 00:55:49 【问题描述】:

在 Node.js 中,有什么方法可以在不使用相对路径的情况下从同一个包中获取文件?例如,这是来自ESLint 的代码的 sn-p。

const rule = require("../../../lib/rules/accessor-pairs"),
     RuleTester  = require("../../../lib/rule-tester");

事实上,我们必须一路走上树 ../../../ 才能到达根部,这不仅令人讨厌。它也很脆弱,因为我无法在不更新所有依赖项引用的情况下移动代码。

但不知何故,Node.js 开发人员似乎在过去 10 年中一直在使用它。除了名为require-self 的第三方依赖项之外,我在文档或堆栈溢出中找不到任何解决此问题的内容。我也找不到明确的说法,使用相对路径是文件在同一模块中需要另一个文件的唯一非 hacky 方式

如果有一种方法可以在 ECMAScript 模块 (ESM) 中指定相对于包根目录的路径,但不能在 CommonJS (CJS) 中指定路径,反之亦然,我也想知道这一点。

需要明确的是,我认为问题没有解决方案。如果有大。否则,我正在寻找权威参考的确认。

【问题讨论】:

过去我通常使用捆绑器解决这个问题,例如via this config 在 Webpack 中,或在其他插件中。您提到的文件移动的其他问题通常由大多数支持 Node 的 IDE 处理。 【参考方案1】:

如果您使用 vscode,那么您很幸运 - !!!!!!项目根目录中的 jsconfig.json 为 commonjs、es6、amd、umd 等处理了这个问题

jsconfig.json 文件指定 javascript 语言服务提供的功能的根文件和选项。


jsconfig.json


  "compilerOptions": 
    "module": "commonjs",
    "baseUrl": ".",
    "paths": 
      "@rules/*": ["path/to/lib/rules/"]
    
  

然后使用别名:

const rule = require('@rules/accessor-pairs'),
     RuleTester  = require('@rules/rule-tester');

阅读更多: https://code.visualstudio.com/docs/languages/jsconfig

【讨论】:

【参考方案2】:

您可以使用包名本身作为包根的“符号链接”。


示例 - foo 包导入相对于 foo 包根目录的 bar 脚本。

package.json


    "dependencies": 
        "foo": "file:./foo"
    

index.js

const foo = require('foo');
console.log(foo.bar);  // prints "hello"

foo/index.js

const bar = require('foo/bar');  // import relative to the package root

module.exports = 
    bar: bar

foo/bar.js

module.exports = 'hello';

【讨论】:

你知道这个需要最早的版本节点吗?? @nntrn 我能够在node@v10.0.0npm@6.14.12 下运行npm installnode index.js(使用nvm use 10.0.0 时自动选择)。旧版本失败了npm install,因为缺少foo/package.json,我没有深入研究这个错误(例如,是否只添加一个虚拟的package.json就足够了)。【参考方案3】:

不一定是相同的 - 如果您正在编写库,这将没有用,但如果您正在编写“最终应用程序” - 实际运行的东西:

一个选项:

如果 NODE_PATH 环境变量设置为以冒号分隔的绝对路径列表,则 Node.js 将在这些路径中搜索模块(如果在其他地方找不到它们)。

所以你可以做任何事情:

1.

export NODE_PATH=.
node app.js
NODE_PATH=. node app.js
// app.js (or whatever your entry point is) before *any* require() calls
process.env.NODE_PATH = __dirname;
require('module').Module._initPaths();

或者,另一种方式:

表示 Node.js 进程启动时加载的入口脚本的 Module 对象。

https://nodejs.org/api/modules.html#modules_require_main

所以你可以这样做:

const rule = require.main.require("./lib/rules/accessor-pairs")

您希望它与根相关的任何时候(假设您的项目结构就是这样)。

【讨论】:

以上是关于Node.js 需要一个相对于包根目录的文件的主要内容,如果未能解决你的问题,请参考以下文章

node rename绝对路径

node.js中static相对路径怎么写

node.js 学习02

前端开发日常 - 12Node.js扫描文件目录

Node.js完整的响应html页面(包括css,js文件)

在 Node.js 中,我如何知道 `this` 模块的路径?