CommonJS和ES Modules本质是不同环境与时代的模块系统:CJS用require/module.exports、运行时同步加载、值拷贝;ESM用import/export、编译时静态解析、实时绑定;二者语法、执行模型、缓存机制及环境支持均不可混用。

CommonJS 和 ES Modules(ESM)不是“选哪个更好”的问题,而是“用在哪儿、怎么用对”的问题。它们本质是不同环境和时代下的产物,语法、加载时机、执行模型都不可混用。
语法写法和导出导入方式不同
CommonJS 用 require() 和 module.exports / exports;ESM 用 import 和 export。
- CJS 导出支持多种写法:直接赋值
module.exports = {...},或逐个挂载exports.fn = () =>{};但exports = {...}会失效(因为 exports 只是 module.exports 的引用) - ESM 分命名导出(
export const a = 1)和默认导出(export default xxx),导入时对应使用import {a} from或import xxx from - CJS 导入得到的是值的拷贝(基本类型)或对象引用副本;ESM 导入的是实时绑定(live binding),原模块改了,导入处也会同步更新
加载时机与执行模型根本不同
CJS 是运行时动态加载,ESM 是编译时静态解析。
基于三引擎设计,从微信文章、新闻和博客网页提取干净内容,支持标题作者日期元数据,多格式和批量处理。
- require() 可以出现在任意位置:if 里、函数里、循环中都能调,适合条件加载或插件式扩展
- import 必须写在顶层作用域:不能放在 if 或函数内;否则报错——这是为了支持构建工具做静态分析(比如 Tree Shaking)
- CJS 加载是同步阻塞的,适合本地文件系统;ESM 天然支持异步(
import()返回 Promise),更适合网络加载场景
顶层能力与模块行为差异明显
ESM 支持顶层 await,CJS 不支持;模块缓存机制也不同。
立即学习“Java免费学习笔记(深入)”;
- ESM 允许在模块顶层写
const data = await fetch(...),整个模块变成异步模块;CJS 中只能把异步逻辑包进函数再导出 - CJS 模块首次加载后缓存,后续 require 直接返回缓存结果;ESM 同样缓存,但它的模块图在解析阶段就已确定,不依赖执行顺序
- CJS 中 this 指向 module.exports;ESM 中顶层 this 是 undefined
环境支持与互操作需谨慎处理
Node.js 默认用 CJS,但已全面支持 ESM;浏览器只认 ESM;两者共存时要注意转换规则。
- Node.js 中启用 ESM 需加
"type": "module"字段或使用 .mjs 后缀;CJS 文件则保持 .js + package.json 无 type 字段 - 两者不能直接混用:
import不能直接引入 CJS 模块(除非构建工具自动转换),require()也不能直接加载 ESM 文件(会报错) - Node.js 提供
createRequire工具可在 ESM 中模拟 require 行为,但仅限于加载 CJS 模块,不推荐日常使用

















