ESModule和Commonjs模块的区别

首页 编程分享 JQUERY丨JS丨VUE 正文

Rkgua 转载 编程分享 2026-05-05 20:05:57

简介 ES Module(ESM)和 CommonJS(CJS)是 JavaScript 中两种主流的模块化规范,以下从几个角度进行分析


ES Module(ESM)和 CommonJS(CJS)是 JavaScript 中两种主流的模块化规范。ESM 是 ES6 推出的官方标准,而 CommonJS 则是 Node.js 早期采用的模块化方案。

以下从几个核心角度为你详细拆解:

1. 核心差异速览表

对比角度 CommonJS (CJS) ES Module (ESM)
基本语法 require() 导入,module.exports 导出 import 导入,export 导出
加载时机 运行时加载(动态) 编译时加载(静态)
加载方式 同步加载 异步加载(浏览器端)
导出本质 值的拷贝(浅拷贝) 值的引用(Live Binding)
代码优化 不支持 Tree Shaking 支持 Tree Shaking
顶层 this 指向 module.exports undefined(严格模式)

2. 深度解析各个角度

语法与规范来源

  • CommonJS:是社区提出的规范,主要用于 Node.js 服务端环境。它的语法非常直观,使用 require() 来引入模块,使用 module.exportsexports 来向外暴露功能。
  • ES Module:是 ECMAScript 2015 (ES6) 的官方语言标准,旨在统一浏览器和服务端的模块化。它使用 importexport 关键字,语法更加语义化,支持命名导出和默认导出。

加载时机与方式(最核心的区别)

  • CommonJS 是“运行时同步加载”:当你代码执行到 require() 这一行时,才会去加载并执行对应的模块文件。这种方式在服务端(读取本地硬盘文件)非常高效,但在浏览器端会因为网络请求阻塞页面渲染,所以浏览器不原生支持。
  • ES Module 是“编译时静态加载”:JS 引擎在解析代码的阶段(编译时),就会通过分析 importexport 语句,提前确定好模块之间的依赖关系。在浏览器中,ESM 默认是异步加载的,不会阻塞 HTML 的解析。

导出的本质:值拷贝 vs 值的引用 这是两者在实际开发中最容易产生 Bug 的差异点:

  • CommonJS(值拷贝):导出的是模块内部变量的一个副本。如果模块内部修改了这个变量,外部引入的地方是感知不到的。
    // CommonJS 示例
    // counter.js
    let count = 0;
    module.exports = { count };
    setTimeout(() => { count = 1; }, 1000); // 内部修改
    
    // main.js
    const { count } = require('./counter.js');
    console.log(count); // 0
    setTimeout(() => { console.log(count); }, 1100); // 依然是 0,因为是拷贝的旧值
    
  • ES Module(值的引用 / Live Binding):导出的是对模块内部变量的动态引用。当模块内部修改了变量,所有引入该变量的地方都会同步更新。
    // ESM 示例
    // counter.js
    export let count = 0;
    setTimeout(() => { count = 1; }, 1000); // 内部修改
    
    // main.js
    import { count } from './counter.js';
    console.log(count); // 0
    setTimeout(() => { console.log(count); }, 1100); // 1,实时同步了最新值
    

代码优化(Tree Shaking)

  • ES Module:由于它是静态的,打包工具(如 Webpack、Rollup、Vite)可以在打包阶段就分析出哪些代码被使用了,哪些没有。未被使用的代码(Dead Code)会被直接剔除,这个过程叫 Tree Shaking(摇树优化),能显著减小打包体积。
  • CommonJS:由于 require() 可以在代码运行时动态执行(比如写在 if 判断里),打包工具很难在编译阶段确定到底引用了哪些模块,因此无法有效支持 Tree Shaking。

运行环境与兼容性

  • CommonJS:Node.js 的默认模块规范,生态极其成熟。在浏览器中无法直接使用,必须通过 Webpack、Browserify 等工具打包转换。
  • ES Module:现代浏览器原生支持(通过 <script type="module">),也是现代前端框架(Vue3, React)和构建工具(Vite)的首选。Node.js 从 v12 版本后也开始支持 ESM,但需要在 package.json 中配置 "type": "module" 或使用 .mjs 后缀。

总结建议: 在现代前端开发和新的 Node.js 项目中,优先推荐使用 ES Module,因为它更标准、性能更好且支持代码优化。但在维护一些老旧的 Node.js 项目或依赖某些仅支持 CJS 的第三方库时,你依然会频繁接触到 CommonJS。

转载链接:https://juejin.cn/post/7634966420486045750


Tags:


本篇评论 —— 揽流光,涤眉霜,清露烈酒一口话苍茫。


    声明:参照站内规则,不文明言论将会删除,谢谢合作。


      最新评论




ABOUT ME

Blogger:袅袅牧童 | Arkin

Ido:PHP攻城狮

WeChat:nnmutong

Email:nnmutong@icloud.com

标签云