NodeJS 使用 ES6 Modules 时获取 __dirname 和 __filename
背景
在使用 NodeJS 编写 ES Modules 代码时,是不可以和写 CommonJS 一样直接使用的 __dirname 和 __filename 变量的。
解决
最好的做法是使用 url.fileURLToPath:
1 | import { dirname } from 'path'; |
有的地方会提到 new URL('', import.meta.url).pathname
这种方式,这是并不推荐的,在官方文档对于 url.fileURLToPath 的说明有一些例子:
1 | import { fileURLToPath } from 'url'; |
另外要注意的一点是在 Vite 2 的 vite.config.js
中是不需要这么做的,在这里可以看到 Vite 会替换 vite.config.ts
文件中的 import.meta.url
, __filename
和 __dirname
为对应路径,所以我们可以直接使用。
同时,如果你的 NodeJS 程序只是用来读取文件,是没有太大必要使用 __dirname
的。多数的方法 path 参数是支持 <URL>
的,这意味着通过 new URL
+ import.meta.url
即可,例如:
Method | path param supports |
---|---|
fs.readFile(path[, options], callback) | <string> , <Buffer> , <URL> , <integer> |
fs.readFileSync(path[, options]) | <string> , <Buffer> , <URL> , <integer> |
fs.readdir(path[, options], callback) | <string> , <Buffer> , <URL> |
fs.readdirSync(path[, options]) | <string> , <Buffer> , <URL> , <integer> |
fsPromises.readdir(path[, options]) | <string> , <Buffer> , <URL> |
fsPromises.readFile(path[, options]) | <string> , <Buffer> , <URL> , <FileHandle> |
还有很多方法都支持 <URL>
参数,所以使用 new URL('<path or file>', import.meta.url)
就可以解决问题,不再需要通过 __dirname
和 __filename
。