面试官:你能说说 CommonJS 和 ES Module 的区别吗?
我:……(脑子里只剩下 require 和 import)
说实话,这个问题你一定见过,而且99% 的前端都背过标准答案。
但真要往深了问一句:
- 为什么 ESM 可以 Tree Shaking?CommonJS 不行
- 为什么 ESM 的 import 是“只读的”?
很多人,当场就开始“CPU 过载”。
于是我决定直接把底层逻辑捋清楚,以下就是我对 CommonJS 和 ES Module 一次系统性深挖的记录。
一、什么是 CommonJS?它解决了什么问题?
1. CommonJS 的诞生背景
在早期 JavaScript 只有浏览器环境时,是没有模块系统的:
于是 Node.js 社区提出了一套解决方案:CommonJS(CMJ) 。
👉 注意:CommonJS 是社区标准,不是官方语言层面的规范。
CommonJS 的核心特征
- ✅ 社区标准
- ✅ 使用函数实现(
require)
- ✅ 仅 Node 环境支持
- ✅ 动态依赖,同步执行
2. CommonJS 为什么叫“动态依赖”?
来看一段最典型的代码:
const moduleName = './a.js';
const a = require(moduleName);
const a = require('./a.js');
function require(path) {
const cache = {}
// 1. 如果模块已经加载过,直接返回缓存
if (cache[path]) {
return cache[path].exports;
}
// 2. 创建模块对象
const module = {
id:path
exports: {}
};
// 3. 执行模块代码(用函数包一层)
function _run(exports, require, module, __filename, __dirname) {
// 模块源码在这里执行
}
_run.call(
module.exports,
module.exports,
require,
module,
__filename,
__dirname
);
// 4. 缓存并返回结果
cache[modulePath] = module;
return module.exports;
}