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。