在 Node.js 中启用 ESM 支持需在 package.json 中设置 "type": "module",使 .js 文件默认按 ES 模块解析,支持 import/export;.cjs 为 CommonJS,.mjs 强制为 ESM;ESM 中可用顶层 await 和 import() 动态导入,但 CommonJS 无法直接 require ESM。

在 Node.js 中启用 ESM(ECMAScript Modules)支持,关键是在项目根目录的 package.json 中设置 "type": "module"。这会告诉 Node.js 将所有 .js 文件默认当作 ES 模块处理,启用 import/export 语法。
1. 设置 package.json 的 type 字段
确保你的 package.json 顶层包含:
{
"type": "module"
}
⚠️ 注意:一旦设置了 "type": "module",所有本地 .js 文件都必须使用 ESM 语法(不能用 require() 或 module.exports),否则运行时报错。
- ✅ 允许:
import fs from 'fs';、export default function() {} - ❌ 禁止:
const fs = require('fs');、module.exports = {}
2. 文件扩展名与模块解析规则
Node.js 会根据 "type" 和扩展名决定模块类型:
-
.js文件:受"type": "module"控制 → 默认为 ESM -
.cjs文件:始终为 CommonJS(即使在 module 项目中) -
.mjs文件:始终为 ESM(优先级高于"type")
例如:你想在 ESM 项目里临时用 CommonJS 写一个工具脚本?把它命名为 utils.cjs 即可,里面仍可用 require()。
3. 命令行运行和入口文件
直接运行 ESM 入口文件无需额外标志(只要 package.json 正确配置):
node index.js
但注意以下常见限制:
- 不支持
import()动态导入 JSON(需加assert { type: 'json' }) - 顶层
await只在 ES 模块中允许(即index.js是 ESM 时可用) - 无法通过
require('./index.js')加载 ESM 文件(CommonJS 不能直接requireESM)
4. 兼容旧代码或混合场景
如果项目中既有 ESM 又有 CommonJS 模块,推荐方式是:
- 保持主逻辑用
.mjs或"type": "module"+.js - 将需
require的旧工具封装成.cjs文件 - ESM 中要用 CommonJS 模块?用
import()动态导入(返回 Promise):const legacy = await import('./legacy.cjs');
不建议用 --experimental-loader 或双包结构,除非有特殊构建需求。


















