ES模块和commonJS两种标准下中实现__dirname?一篇文章教你理清楚

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')
  }
};

特点

  1. 所有 .js 文件默认识别为 CJS
  2. 自带全局 __dirname、__filename,零配置
  3. 使用 require()、module.exports / exports
  4. 不会出现 URL、fileURLToPath 相关报错

适用场景

webpack 学习、后端 Node 脚本、旧项目,最推荐新手


二、ESM(package.json 添加 "type": "module")

核心特性

  1. 所有 .js 文件都是 ES Module
  2. 无内置 __dirname、__filename,必须手动计算
  3. 只能使用 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 模块 同样不能 同样不能
相关推荐
掘金挖土5 小时前
前端手摸手跑路之 AI 应用开发(九)
前端·后端
中文呀7 小时前
三维 GIS 离线缓存实战:逆向 CesiumOfflineCache,并亲手为它补上"自动更新"能力
前端
前进前进前进8 小时前
TRAE 全链路实战:做了一个警示牌一键生成器:纯 Canvas、单文件、零依赖
前端
小万7429 小时前
God‘s Eye View 深度解析:15 路公开信号 + CesiumJS 的浏览器级 OSINT 控制台,60 帧渲染的“真实间谍卫星模拟器”
前端
IT星宿9 小时前
浏览器标签页全是一个图标:我用名字哈希生成 favicon,让每个项目都有身份标识
前端
全栈项目管理程序猿9 小时前
ArcGIS JS 基础教程(32):体元系列 - VoxelSlice 体元切片
前端·javascript
拖孩11 小时前
AI 帮我写的小程序「厨菜记」上线满月了,挣了两百块!!!
前端·后端·微信小程序
用户3600555790011 小时前
Kestrel_VLLM - 13 · 为什么排除 MoE FFN Tiling 与 Tensor Core
前端
Hilaku11 小时前
AI 流式输出都用 SSE,什么时候必须换 WebSocket?
前端·javascript·程序员
奇牙coding12 小时前
Codex CLI 升级后多文件编辑静默失效:config.yaml 枚举变更排查与修复指南
java·前端·javascript·ai