Node.js 如何获取当前脚本的路径?
CommonJS 用 __filename 取当前脚本完整路径、__dirname 取所在目录;ES Module 里没有这两个变量,可用 import.meta.url + fileURLToPath 转换,支持的新版也提供 import.meta.filename/dirname。本文给出两种模块体系的写法。
CommonJS:用 __filename(当前文件完整路径)和 __dirname(所在目录)。ES Module:用 import.meta.url 转换。
CommonJS(.cjs 或明确配置为 CommonJS)
console.log('__filename:', __filename); // /path/to/your/script.js
console.log('__dirname:', __dirname); // /path/to/your
典型用途——构造相对于脚本文件的路径,避免相对路径随启动目录漂移:
const path = require('path');
const configPath = path.join(__dirname, 'config.json'); // 永远指向脚本旁边的 config.json
ES Module(.mjs 或 type:module)
__dirname/__filename 在 ESM 里不存在,手写等价物:
import { fileURLToPath } from 'url';
import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
console.log(__dirname);
Node 20.11.0/21.2.0 起,file: ESM 还提供 import.meta.filename 和 import.meta.dirname(22.16.0/24.0.0 起不再标为实验);兼容旧版可继续用上面转换。它们是当前模块路径,不是应用入口;非 file: 模块不适用。
相关但不同的变量
| 变量 | 含义 |
|---|---|
__dirname |
当前模块文件所在目录 |
process.cwd() |
进程当前工作目录,可通过 process.chdir() 改变 |
import.meta.url |
ESM 中当前模块的 file:// URL |
require('./data.json') 里的相对路径基于模块位置;fs.readFile('./data.json') 里的相对路径基于 process.cwd()——这个差异是路径 bug 的高发区,文件操作建议统一用 path.join(__dirname, ...)。
常见问题(FAQ)
Q:打包(webpack/esbuild)后 __dirname 还准吗?
打包器可能保留、替换、模拟或禁用 __dirname,取决于目标平台和配置;不能保证总指向 bundle 所在目录。需要访问的资源要么内联打包,要么用绝对路径/环境变量指定。
Q:__dirname 末尾带斜杠吗?
通常不带,但根目录本身可能带分隔符,如 / 或 C:\。拼接路径用 path.join(__dirname, 'x'),别手写斜杠(Windows 兼容性问题)。
Q:Docker 里 __dirname 是什么?
当前模块在容器内的目录路径(如 /app/src),不是完整文件名;符号链接解析还受 Node 参数影响,与宿主机无关。挂载卷后按容器内路径理解即可。