当前位置: 首页 > news >正文

梳理一下前端模块化规范:CommonJS ESM AMD CMD UMD

前端模块化规范在发展过程中出现过多种规范,大多开发者都对这些名词有个印象,但问起来又有些模糊。本文的目的是做一个梳理,帮助记忆。

先上一张对比表:

类型核心定位语法关键词适用环境特点
CommonJS(CJS)Node.js 默认模块规范require、module.exports、exportsNode.js 服务端、Webpack 打包同步加载、运行时加载、浅拷贝
ESM官方标准模块规范import、export、export default现代浏览器、Node.js v14+异步 / 静态加载、编译时确定依赖、绑定引用
AMD异步模块规范define、require旧版前端项目(RequireJS)依赖前置、异步加载、不阻塞页面
CMD异步模块规范define、require旧版前端项目(SeaJS)依赖就近、按需加载、风格接近 Node
UMD兼容模块格式自执行函数包裹浏览器全局、AMD、CommonJS自动判断环境、一套代码多环境可用
Dual Package双产物发包策略打出 2 个包npm 库、多环境兼容项目同时输出 CJS 和 ESM 产物,工具自动识别

一、CommonJS(CJS)

CommonJS 是 Node.js 的默认模块化规范,也是早期前端打包支持的规范,很多老 Node 项目至今还在使用。

// 导出模块(a.js) // 方式1:整体导出 module.exports = { add: (a, b) => a + b, name: "CommonJS模块" }; // 方式2:单个导出 exports.sub = (a, b) => a - b; // 导入模块(b.js) const mod = require('./a.js'); console.log(mod.add(1, 2)); // 3 console.log(mod.sub(3, 1)); // 2

特点:

  1. 同步加载:在 Node.js 服务端,文件都在本地,同步加载不会有问题。

  2. 浅拷贝:导出的是对象浅拷贝,后续原模块修改该值,导入方拿到的副本不会变。

补充:CommonJS 没有官方缩写,但行业内普遍简称 CJS。

二、ESM —— 官方标准

ESM(ES Modules)是 ECMAScript 官方推出的模块化规范,也是目前前端开发的主流 —— 现代浏览器、Node.js(v14+)、Vue/React 等框架,全部默认支持 ESM。

它解决了 CommonJS 的诸多痛点,比如同步加载、不支持 Tree-Shaking 等,语法也更简洁。

// 导出模块(a.js) // 方式1:命名导出(可多个) export const add = (a, b) => a + b; export const name = "ESM模块"; // 方式2:默认导出(仅1个) export default function sub(a, b) { return a - b; } // 导入模块(b.js) import { add, name } from './a.js'; import sub from './a.js'; console.log(add(1, 2)); // 3 console.log(sub(3, 1)); // 2

特点:

  1. 静态编译:编译时就确定依赖关系,支持 Tree-Shaking(删除无用代码),打包体积更小;浏览器中是异步加载,不阻塞页面。

  2. 绑定引用:导出的是值的引用,原模块修改该值,导入方也会同步变化(和 CommonJS 的 “浅拷贝” 区分)。

三、AMD + CMD

  • AMD(Asynchronous Module Definition),代表工具是 RequireJS,核心是依赖前置—— 一开始就声明所有依赖,异步加载完成后执行回调。
  • CMD(Common Module Definition),代表工具是 SeaJS,核心是依赖就近—— 用到某个模块时,再去 require,写法风格接近 Node 的 CommonJS。
  • AMD 是依赖前置、提前加载;CMD 是依赖就近、懒执行,两者现在都已淘汰,不必深入学习。

四、UMD

UMD(Universal Module Definition),直译是 “通用模块定义”,它不是一种新的规范,而是一种兼容方案—— 一套代码,能同时适配 CommonJS、AMD、浏览器全局变量。自动判断当前运行环境,选择对应的模块化方式。

标准无依赖 UMD 写法:

(function (root, factory) { // AMD if (typeof define === 'function' && define.amd) { define(factory); } // CommonJS else if (typeof module === 'object' && module.exports) { module.exports = factory(); } // 浏览器全局 else { root.MyModule = factory(); } })(this, function () { // 模块逻辑 return { add: (a, b) => a + b }; });

特点:万能兼容,一套打包产物能在任何环境运行;但缺点是代码冗余,现在的开源库已经很少用 UMD,转而用更简洁的 Dual Package。

五、Dual Package —— 双产物包

它是一种发包策略,同时打包输出 CJS 和 ESM 两种产物,让项目既能支持 CommonJS,也能支持 ESM。

现代 npm 库的标准配置:

{ "name": "my-utils", "main": "dist/index.cjs", "module": "dist/index.mjs", "exports": { ".": { "import": "./dist/index.mjs", "require": "./dist/index.cjs" } } }

优势:不用写环境判断代码,比 UMD 更简洁;适配所有现代项目和老 Node 项目,是目前开源库的主流发包方式。

六、package.json 的 type 字段

type是 Node.js 官方字段,用于声明模块化格式,影响.js文件的解析方式。

  • "type": "module":按 ESM 解析

  • 不配置:默认按 CommonJS 解析

七、Webpack 打包指定输出规范

Webpack 5 推荐使用output.library.type

输出 CommonJS:

module.exports = { output: { filename: 'bundle.js', library: { type: 'commonjs2' } } };

输出 ESM:

module.exports = { output: { filename: 'bundle.mjs', library: { type: 'module' } }, experiments: { outputModule: true } };

输出 UMD:

module.exports = { output: { library: { type: 'umd' } } };

输出双产物:分别用两份配置打包两次即可。

总结

  1. 前端项目(Vue/React/Vite/Webpack):一律用 ESM。

  2. Node.js 项目:老项目用 CommonJS,新项目推荐 ESM。

  3. 开发 npm 库:使用 Dual Package 双产物;极老环境可额外打包 UMD。

http://www.jsqmd.com/news/778944/

相关文章:

  • RK3128红外遥控调试避坑实录:解决按键失灵、无法唤醒和关机开机问题
  • 本地AI代理框架palot:从YAML配置到实战应用全解析
  • 2026濮阳正规医美整形推荐榜:这一家口碑认证别错过 - 速递信息
  • day1召开团队项目计划会议
  • 【人生底稿 22】嘉兴突击出差记:一场仓促行程,埋下湖南项目的伏笔
  • 四十三、网络编程(下)——TCP 编程与 HTTP 入门
  • 2026年4月商务车改装定制门店口碑推荐,商务车座椅改装/漆面保护膜/隐形车衣/商务车改装,商务车改装品牌哪家专业 - 品牌推荐师
  • PHP怎么处理Paragonie安全库_PHP加密与随机数生成【技巧】
  • 吃透C++ AVL树:原理+完整实现,新手也能轻松上手
  • Keil uVision仿真器进阶:如何正确配置外部时钟与查看SYSCLK频率
  • Visual Studio 2022实战:一步步搭建C++ ADS客户端与TwinCAT3 PLC的浮点数通信Demo
  • 追风筝的人
  • 为AI编码助手集成sh-guard:语义化Shell命令安全防护实践
  • MatrixFusion 全视频融合,一屏统览危化全域态势
  • AS5600磁编码器避坑指南:从I2C通信失败到角度跳变的5个常见问题及解决方法
  • (初阶) 从零开始:Tushare环境配置与基础数据获取
  • 开源Zapier集成工具:连接FreedomSoft CRM实现房地产投资自动化
  • 基于物理约束的图像重照明技术解析与实践
  • 团队个人任务认领
  • 【无标题】NeuroRebuild 动态孪生,虚实同步秒级应急推演
  • Code For Better 谷歌开发者之声——开发者必备神器
  • Stackmoss:构建生产级AI原生应用的一体化框架实战指南
  • 认识BLE MESH架构和实际开发过程
  • Gantry框架深度解析:轻量级Go Web开发实践与架构设计
  • 鸿蒙NEXT开发从零到一:手把手搭建开发环境并发布第一个应用
  • 2026年南京市实测手表回收商家,亲测推荐TOP5分享 - 速递信息
  • DAY .2 数据结构之反转链表2.牛客网BM2
  • 别再死记硬背了!用Wireshark抓包实战,5分钟搞懂PCIe配置空间的BAR寄存器
  • SEO站群系统源码 SEO优化系统 单页关键词排名网站源码
  • 从奈奎斯特图到相位裕度:一个更直观的视角,理解运放稳定性分析与补偿