# CommonJS与ESM是什么关系?

CommonJSESM(ECMAScript Modules) 本质上是 JavaScript 的两套模块规范

它们解决的是同一个问题:

如何把代码拆分成多个文件,并且互相引用。

# 模块化发展历史

第一阶段:没有模块

以前 JavaScript 只有:

<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
1
2
3

所有变量都挂在全局:

var user = {}
1

容易冲突。

第二阶段:Node.js 推出 CommonJS

2009年,Node.js 出现。

当时浏览器没有模块标准。

Node.js 自己设计了一套:

// user.js
module.exports = {
  name: 'Tom'
}
1
2
3
4
// app.js
const user = require('./user')

console.log(user.name)
1
2
3
4

这就是:CommonJS

特点:

require()
module.exports
exports
1
2
3

第三阶段:ES6推出ESM

2015年,JavaScript 官方(ECMAScript)终于推出标准模块:

export default {
  name: 'Tom'
}
1
2
3
import user from './user.js'
1

这就是:

ESM ES Module ECMAScript Module

特点:

import export export default

# 两者关系

可以理解为:

CommonJS  = Node.js 自己发明的模块系统

ESM       = JavaScript 官方标准模块系统
1
2
3

就像:

微信支付 ← 企业方案

银行卡支付 ← 国家标准

后来大家逐渐统一到标准方案。

# 语法对比

CommonJS

导出:

module.exports = {
  name: 'Tom'
}
1
2
3

导入:

const user = require('./user')
1

ESM

导出:

export default {
  name: 'Tom'
}
1
2
3

导入:

import user from './user.js'
1

# 加载机制区别

这是最大的区别。


CommonJS

同步加载

const user = require('./user')
1

执行到这里:

停下来
↓
读取文件
↓
执行文件
↓
返回结果
↓
继续执行
1
2
3
4
5
6
7
8
9

所以:

同步
1

适合服务器。

因为磁盘读取很快。


ESM

静态加载

import user from './user.js'
1

运行前就已经知道依赖关系:

编译阶段
↓
分析 import
↓
建立依赖图
↓
运行
1
2
3
4
5
6
7

因此:

Tree Shaking
按需加载
代码分割
1
2
3

都能实现。

Last Updated: 6/12/2026, 4:20:22 AM