在 NodeJS 中使用绝对路径导入 ES6 模块而不使用 Babel/Webpack

jon*_*bbs 8 javascript node.js node-modules typescript es6-modules

我有一个普通的旧 NodeJS 项目(使用 Typescript),我真的很难找出如何为本地文件执行 ES6 导入,而不必一直执行“../../../foo/bar”。

有很多类似的问题,但似乎都围绕着我没有使用的 babel/Webpack 展开。

如果我执行以下操作:

import foo from `/bar`
Run Code Online (Sandbox Code Playgroud)

它在我 PC 的根文件夹(例如 c:/bar)中查找它并失败。

我曾尝试使用 .env 文件并将 NODE_PATH 设置为各种铰链(“/”、“.”等),但没有运气。我也试过在我的 package.json 中设置“type: 'module'”,我的 tsconfig.json 文件有 {"baseUrl": "."}

所以我想我已经尝试了我能找到的所有答案。我只是在错误的组合中使用它们还是解决方案有所不同?

aka*_*ppi 9

以下是我为此使用的两个技巧:Node.js 和原生 ES 模块。

  1. file:依赖关系

<project root>/bar如果您想从下两级的子包访问,请将其添加到package.json依赖项中:

    "@local/bar": "file:../../bar",
Run Code Online (Sandbox Code Playgroud)

..bar使该子包可以作为@local/bar.

虽然相对路径仍然存在,但它们现在都在package.json文件中,并且源永远不需要知道。

  1. 使用动态import()

选择常量的根文件夹路径并执行以下操作:

const foo = await import(`${rootPath}/bar`);
Run Code Online (Sandbox Code Playgroud)


how*_*d_9 7

使用“导入”属性

截至 2023 年 3 月,消除 NodeJS 相对路径的一个好方法是imports使用package.json. 想要了解更多信息,请参考这篇文章:

在下面的代码中,#root 是项目根目录。

(如果这个答案和这篇文章对您有帮助,请点赞。谢谢!)

对于 CommonJS 风格的 JavaScript:

// package.json
{
  "imports": {
    "#root/*.js": "./*.js"
  }
}

// main.js:
const Source = require('#root/path/to/Source.js');

// Source.js:
module.exports = class Source {
  // ...
}

Run Code Online (Sandbox Code Playgroud)

对于 ECMAScript 风格的 JavaScript:

// package.json:
{
  "type" : "module",
  "imports": {
    "#root/*.js": "./*.js"
  }
}

// main.js
import { Source } from '#root/path/to/Source.js';

// Source.js:
export class Source {
  // ...
}

Run Code Online (Sandbox Code Playgroud)

优点:

  • 不需要“导入”或“要求”任何额外的包(没有 Babel.js、没有 Webpack、没有 RequireJS)。安装 NodeJS 后,此方法开箱即用。

  • IDE 链接按预期工作(按住 Ctrl 键单击类名可直接跳转到源文件。此外,移动源文件(通过拖放)将自动更新文件路径引用。已在 和 上进行测试WebStorm 2022.3.2VS Code 1.76.2

  • 适用于.mjs(ECMAScript 模块系统)和.cjs(CommonJS)文件类型。请参阅有关 .cjs 和 .mjs 的参考帖子。

  • 无需修改保留node_modules目录

  • 无需在操作系统级别设置任何 linux 文件链接


小智 -1

我不确定“本地文件无需执行任何操作"../../../foo/bar"”是什么意思

让我解释一下 Javascript 如何处理导入。这是基本的文件夹结构。

C:Users/NAME/Project/randomfolder/bar.js


- Project
  - Random Folder
    - foo.js
  - bar.js
Run Code Online (Sandbox Code Playgroud)

选项 1 对于您将要做的 95% 的事情来说可能是更好的选择

假设您正在尝试将 foo.js 导入到 bar.js 中,我们首先使用 a 获取 bar.js 的当前位置,.因此它是

import foo from "./Random Folder/foo.js"
Run Code Online (Sandbox Code Playgroud)

如果您采用另一种方式,.仍然用于表示获取文件夹结构中的当前位置,但您传递第二个...然后传递 a/来进入文件夹。因此,要将 bar.js 导入到 foo.js 中,它看起来像这样:

import bar from "../bar.js"
Run Code Online (Sandbox Code Playgroud)

我们要进入一个文件夹,然后寻找我们想要的文件。

选项2

但是,如果您知道您的文件夹结构将非常大,并且您将始终导入向上或向下的几个文件夹,为什么不创建一个变量,然后使用字符串文字。

  let folder = `../../../`
  import test from `${folder}foo`
Run Code Online (Sandbox Code Playgroud)

您有几种选择来处理您想做的事情。

选项 3 对于 NodeJS 和模块

如果您使用 NodeJS 并且想要获取非相对路径,请使用app-root-path模块。它可以让您始终获得项目根目录,然后相应地深入到文件中。这可以通过字符串文字来完成。

var appRoot = require('app-root-path');
import foo from appRoot + "/foo/bar/folders/bla/bla"

or

import foo from `${appRoot}/foo/bar/folders/bla/bla` <-- string literals

Run Code Online (Sandbox Code Playgroud)