Node.js 18 ES模块中__dirname和__filename消失了?教你一招搞定!

1,698 阅读2分钟

最近在写一个脚手架工具时,决定采用 Node.js 的 ES 模块(ESM)开发。当我习惯性地用 __dirname 获取当前模块的目录路径时,却直接报错了:

ReferenceError: __dirname is not defined in ES module scope

我尝试了 __filename,结果也是同样的错误。这就离谱了!要知道,__dirname__filename 可是 Node.js 中获取当前文件和目录路径的经典工具,怎么突然说没就没了?

于是我去翻了 Node.js 的官方文档,官方文档说明如下(nodejs.org/docs/latest…

image.png

在 CommonJS 模块中,__dirname__filename 是默认可用的全局变量,随时可以拿来用。而到了 ES 模块里,这俩东西就消失了。取而代之的,是一个叫 import.meta.url 的新玩意儿。

这个 import.meta.url 是当前模块的 URL,格式看起来像这样:

file:///path/to/your/module.js

简单来说,ES 模块觉得你应该用这种更标准的方式获取模块路径。但问题是,这玩意儿直接用的话不太方便,得转换成普通的文件路径才行。

既然官方文档已经给了方向,那就试着把问题解决掉:

// 引入 Node.js 自带的模块
import path from 'node:path';
import { fileURLToPath } from 'node:url';

// 转换成 __filename 和 __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 输出结果
console.log('当前文件路径:', __filename);
console.log('当前目录路径:', __dirname);
  • import.meta.url:这是 ES 模块提供的上下文变量,代表当前模块的 URL。
  • fileURLToPath:Node.js 内置的一个小工具,可以把文件的 URL 转成常见的文件路径。
  • path.dirname:从文件路径中提取出所在目录的路径。

通过这段代码,你就可以在 ES 模块里重新拥有类似 __dirname__filename 的功能了。

后来又查看了其他版本的,发现从nodejs 20.11.1 版本开始可以直接使用 import.meta.filenameimport.meta.dirname了,不用像上面那么麻烦了

image.png