ESM和CJS的区别

142 阅读2分钟

ESM(ECMAScript Modules)和 CJS(CommonJS)是 JavaScript 中两种不同的模块系统,它们的主要区别在于语法、加载机制、执行时机、适用环境等方面。下面是详细对比:


📦 1. 基本概念

模块系统全称简介
ESMECMAScript ModulesJavaScript 官方标准模块系统(ES6 引入)
CJSCommonJSNode.js 最初使用的模块系统

🧾 2. 语法对比

✅ ESM(推荐使用)

// 导出
export const name = 'vite'
export function sayHello() {}

// 默认导出
export default function () {
  console.log('default export')
}

// 导入
import { name, sayHello } from './module.js'
import defaultFn from './module.js'

✅ CJS(传统 Node.js)

// 导出
const name = 'vite'
function sayHello() {}
module.exports = { name, sayHello }

// 导入
const { name, sayHello } = require('./module')

⚙️ 3. 加载机制

特性ESMCJS
加载方式静态加载(编译时确定依赖)动态加载(运行时 require)
是否异步是(import 是异步)否(require 是同步)
是否支持 tree-shaking✅ 支持❌ 不支持
是否支持顶层 await✅ 支持❌ 不支持(需额外配置)

🧪 4. 执行时机

  • ESM 是在代码执行前解析所有 import(提前加载)。
  • CJS 是在代码执行时遇到 require 才加载(懒加载)。

🌍 5. 适用环境

环境支持情况
浏览器✅ 原生支持 ESM(import)
Node.js✅ 支持 ESM(需要 .mjs 或 "type": "module")
Webpack/Vite 等构建工具✅ 推荐使用 ESM
老旧 Node.js 项目✅ 默认使用 CJS

🛠️ 6. 文件扩展名和 package.json 配置

在 Node.js 中使用 ESM:

  • 文件扩展名为 .mjs,或
  • 在 package.json 中添加:
{
  "type": "module"
}

否则 Node.js 默认使用 CJS 模式。


📚 7. 示例对比总结

特性ESMCJS
导入语法import/exportrequire/module.exports
加载方式静态动态
执行顺序先加载再执行边执行边加载
Tree-shaking✅ 支持❌ 不支持
顶层 await✅ 支持❌ 不支持
浏览器支持❌(需打包)

✅ 总结:什么时候用哪个?

场景推荐模块系统
前端项目(Vite、Webpack)✅ ESM(import/export)
Node.js 新项目✅ ESM(推荐)
老旧 Node.js 项目✅ CJS(兼容性)
发布 npm 包✅ 同时支持 ESM + CJS(双构建)