最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Node.js require a file relative to the root of the package - Stack Overflow

programmeradmin5浏览0评论

In Node.js, is there any way to require file from the same package without using relative paths? For example, here's a snippet of code from ESLint.

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

The fact that we have to walk all the way up the tree ../../../ to get to the root is not only annoying. It's also brittle, because I can't move the code without updating all of dependency references.

Yet somehow Node.js developers seem to have lived with it the past 10 years. I can't find anything in the docs or Stack Overflow that solves this problem other than a third-party dependency called require-self. Nor have I been able to find a definitive statement that using relative paths is the only non-hacky way for a file to require another file in the same module.

If there's a way to specify a path relative to the package root in ECMAScript Modules (ESM) but not CommonJS (CJS), or vice versa, I would like to know that as well.

To be clear, I don't think there is a solution to the problem. If there is great. Otherwise, I'm looking for confirmation with an authoritative reference.

In Node.js, is there any way to require file from the same package without using relative paths? For example, here's a snippet of code from ESLint.

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

The fact that we have to walk all the way up the tree ../../../ to get to the root is not only annoying. It's also brittle, because I can't move the code without updating all of dependency references.

Yet somehow Node.js developers seem to have lived with it the past 10 years. I can't find anything in the docs or Stack Overflow that solves this problem other than a third-party dependency called require-self. Nor have I been able to find a definitive statement that using relative paths is the only non-hacky way for a file to require another file in the same module.

If there's a way to specify a path relative to the package root in ECMAScript Modules (ESM) but not CommonJS (CJS), or vice versa, I would like to know that as well.

To be clear, I don't think there is a solution to the problem. If there is great. Otherwise, I'm looking for confirmation with an authoritative reference.

Share Improve this question edited Mar 1, 2021 at 13:51 Patrick McElhaney asked Mar 1, 2021 at 13:39 Patrick McElhaneyPatrick McElhaney 59.4k41 gold badges137 silver badges170 bronze badges 1
  • In the past I've typically solved this issue using a bundler e.g. via this config in Webpack, or plugins in others. The other issues you mentioned re files moving are typically handled by most IDEs that have Node support tbh. – James Commented May 24, 2021 at 19:52
Add a ment  | 

3 Answers 3

Reset to default 4 +50

You can use the package name itself as a "symlink" to the package root.


Example - foo package imports bar script relative to the foo package root.

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';

Not necessarily the same package - if you are writing libraries this won't be useful, but if you are writing the "final application" - the thing that actually gets run:

One option:

If the NODE_PATH environment variable is set to a colon-delimited list of absolute paths, then Node.js will search those paths for modules if they are not found elsewhere.

So you can do any of:

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

Or, another way:

The Module object representing the entry script loaded when the Node.js process launched.

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

So you can just do:

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

anytime you want it to be relative to the root (assuming that is how you have your project structured).

If you use vscode then you're in luck - !!!! jsconfig.json in project root handles this masterfully for monjs, es6, amd, umd, etc

The jsconfig.json file specifies the root files and the options for the features provided by the JavaScript language service.


jsconfig.json

{
  "pilerOptions": {
    "module": "monjs",
    "baseUrl": ".",
    "paths": {
      "@rules/*": ["path/to/lib/rules/"]
    }
  }
}

and then to use the alias:

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

Read more: https://code.visualstudio./docs/languages/jsconfig

发布评论

评论列表(0)

  1. 暂无评论