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

问题描述 投票:0回答:4

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

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

如果我执行以下操作:

import foo from `/bar`

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

我尝试使用 .env 文件,并将 NODE_PATH 设置为各种参数(“/”、“.”等),但没有成功。我还尝试在 package.json 中设置“type: 'module'”,并且我的 tsconfig.json 文件具有 {"baseUrl": "."}

所以我想我已经尝试了我能找到的所有答案。我只是以错误的组合进行操作还是解决方案有所不同?

javascript node.js typescript node-modules es6-modules
4个回答
9
投票

这是我为此使用的两个技巧,即 Node.js 和原生 ES 模块。

  1. file:
    依赖关系

如果您想从下两级的子包访问

<project root>/bar
,请将其添加到
package.json
依赖项中:

    "@local/bar": "file:../../bar",

..使

bar
可用于所述子包作为
@local/bar
.

虽然相对路径仍然存在,但它们现在都在

package.json
文件中,并且源永远不需要知道..

  1. 使用动态
    import()

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

const foo = await import(`${rootPath}/bar`);

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 {
  // ...
}

对于 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 {
  // ...
}

优点:

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

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

    WebStorm 2022.3.2
    VS Code 1.76.2 上测试
    。)

  • 适用于

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

  • 无需修改保留的

    node_modules
    目录

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


1
投票

这对我来说实现起来非常简单,在 VSCode 中使用 Typescript。

tsconfig.json
中,我在
"baseUrl": "./",
下添加了
compilerOptions

重启 VSCode 后,VSCode 将自动使用伪绝对路径导入。

路径不会以

/
开头,它仍然指向您的驱动器根目录。

如果位于当前文件下方,它仍然会使用

./relative/path
,但不再使用
../../tree/traversing

然后我将packages.json中的dev设置为

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "dev": "cross-env NODE_PATH=./ nodemon ./app.ts"
},

我用

cross-env
。您可以使用
set
命令和
nodemon
自动重新加载更改文件。

NODE_PATH
设置为
./
告诉 NodeJS 执行 Visual Studio 和 TypeScript 正在执行的操作。

我的

package.json
目录中有
src
。您可能不会,并且可能需要更改一些路径来进行调整。


-1
投票

我不确定“本地文件无需执行

"../../../foo/bar"
”是什么意思

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

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


- Project
  - Random Folder
    - foo.js
  - bar.js

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

假设您正在尝试将 foo.js 导入到 bar.js 中,我们首先使用

.
获取 bar.js 的当前位置,所以它会是

import foo from "./Random Folder/foo.js"

如果您采用另一种方式,

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

import bar from "../bar.js"

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

选项2

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

  let folder = `../../../`
  import test from `${folder}foo`

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

选项 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

© www.soinside.com 2019 - 2024. All rights reserved.