📜  __dirname 未在 es 模块范围内定义 (1)

📅  最后修改于: 2023-12-03 15:13:14.289000             🧑  作者: Mango

Node.js 报错:__dirname 未在 es 模块范围内定义

当你在使用 ECMAScript 模块(ESM)特性进行模块加载时,当使用 __dirname 时,有可能会出现如下报错:

ReferenceError: __dirname is not defined

这是因为在 ESM 中,没有像 CommonJS 中的 __dirname 可以直接获取当前模块所在目录的对象。ESM 中只能通过 import.meta.url 获取当前模块文件的 URL,然后再通过一些代码处理得到当前模块所在目录。

以下是获取 __dirname 的一些方法:

方法一:添加 --experimental-modules 参数

当你在 Node.js 中设置启动参数时,使用 --experimental-modules 参数开启 ESM 特性:

node --experimental-modules your_app.js

那么在你的应用中,就可以直接使用 __dirname 了。

方法二:引入 path 模块获取目录信息

另一种方法是,通过引入 path 模块,再通过 path.dirname(import.meta.url) 获取当前模块所在目录:

import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __dirname = dirname(fileURLToPath(import.meta.url));

解析:

  • 构造函数 URL 的实例对象,可以直接获取当前模块源代码的 URL
  • 通过 fileURLToPath,把 URL 转为本地文件路径
  • 通过 path.dirname,获取当前路径的文件夹路径

特别需要注意的是,此方法中的 import.meta.url 返回的 URL 包含 file://,需要通过 fileURLToPath 转成本地路径。

方法三:使用变量保存项目根路径

另一种方式是,在应用启动时,通过一些方式(如读取环境变量、动态获取)获取项目根路径,保存到一个变量中,在以后的代码中使用这个变量来获取绝对路径。

const APP_ROOT = process.cwd();

这种方式虽然实现简单,但是不可避免会带来一些概念上的混乱,比如说在不同的模块中可能会获取到不同的路径。

总结

当你在使用 ECMAScript 模块(ESM)进行模块加载时,需要注意 __dirname 是不存在的,相应的,需要换用其他方式获取当前模块所在目录。我们可以通过添加启动参数、引入 path 模块或者自定义变量等方式来获取当前模块的路径。在实际开发中,需要根据项目实际情况,合理选用合适的方式来获取路径信息。