CommonJS / ESM 中 __dirname 的实现方式
开头先了解一下console.log(import.meta)的输出结果和node版本 node-v 指令 以便更好了解。 
一、CommonJS(默认,package.json 无 "type":"module")
1. 内置全局变量,直接使用
无需导入任何模块,文件内原生存在 __dirname / __filename
js
lua
// webpack.config.cjs / index.js(CJS)
const path = require('path');
// 当前文件所在文件夹绝对路径
console.log(__dirname);
// 当前文件完整绝对路径
console.log(__filename);
module.exports = {
output: {
path: path.resolve(__dirname, 'dist')
}
};
特点
- 所有
.js文件默认识别为 CJS - 自带全局
__dirname、__filename,零配置 - 使用
require()、module.exports / exports - 不会出现 URL、fileURLToPath 相关报错
适用场景
webpack 学习、后端 Node 脚本、旧项目,最推荐新手
二、ESM(package.json 添加 "type": "module")
核心特性
- 所有
.js文件都是 ES Module - 无内置
__dirname、__filename,必须手动计算 - 只能使用
import / export default,不能用require、module.exports
方式 1:兼容全 Node 版本(通用稳定写法,webpack 配置首选)
依赖内置 url + path 模块,import.meta.url 是文件自带 file:// 协议地址
js
javascript
// webpack.config.js(ESM)
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
// 把 file:// 链接转为本地文件绝对路径,这里取__filename1,避免混淆
const __filename1 = fileURLToPath(import.meta.url);
// 从文件路径取出所在目录 = __dirname
const __dirname = dirname(__filename1);
export default {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist')
}
};
关键禁忌
fileURLToPath只能接收import.meta.url- 不能传入
import.meta.dirname(已经是字符串,会报 URL 协议错误)
方式 2:Node 20.11+ 简化写法(简写,不兼容低版本)
Node20 新增 import.meta.dirname 语法糖,直接等价上面整套代码
js
javascript
import path from 'path';
const __dirname = import.meta.dirname;
export default {
output: {
path: path.resolve(__dirname, 'dist')
}
};
缺点
换 Node18/16 环境直接报错,不适合通用项目
三、关键踩坑区分
1. ESM 报错 Cannot use import statement outside a module
package.json 没加 "type":"module",但文件用了 import → 切换 CJS 或开启 type:module
2. ESM 报错 __dirname is not defined
开启 type:module 后,原生全局变量消失,必须手动用 fileURLToPath 生成
3. 报错 ERR_INVALID_URL_SCHEME
错误写法:fileURLToPath(import.meta.dirname)原因:import.meta.dirname 是本地路径字符串,不是 file:// URL,只能传 import.meta.url
四、两种规范对比表
表格
| 对比项 | CommonJS(无 type:module) | ESM("type":"module") |
|---|---|---|
__dirname |
全局自带,直接用 | 无,需手动计算 |
| 导入导出 | require() / module.exports |
import / export default |
| 路径获取 | __dirname |
fileURLToPath(import.meta.url) |
| Node 版本兼容 | 全版本兼容 | Node14.13+ 完整支持 |
| webpack 配置推荐度 | ⭐⭐⭐⭐⭐ 新手首选 | ⭐⭐⭐ 需额外处理路径 |
| 浏览器代码能否用 Node 模块 | 同样不能 | 同样不能 |