AMD、CMD、CommonJS、UMD、ESM( JS模块化规范)
随着前端发展的不断进步,JavaScript的模块化不仅在NodeJS中应用,也被拿到了浏览器上得到应用,所以出现了一些模块化的规范
AMD(Asynchromous Module Definition - 异步模块定义)
AMD是RequireJS在推广过程中对模块定义的规范化产出,AMD是异步加载模块,推崇依赖前置。
1 2 3 | define( 'module1' , [ 'jquery' ], ($) => { //do something... }); |
代码中依赖被前置,当定义模块(module1)时,就会加载依赖(jquery)
CMD(Common Module Definition - 公共模块定义)
CMD是SeaJS在推广过程中对模块定义的规范化产出,对于模块的依赖,CMD是延迟执行,推崇依赖就近。
1 2 3 4 5 6 7 8 | define((require, exports, module) => { module.exports = { fun1: () => { var $ = require( 'jquery' ); return $( '#test' ); } }; }); |
如上代码,只有当真正执行到fun1方法时,才回去执行jquery。
同时CMD也是延自CommonJS Modules/2.0规范
CommonJS(cjs)
提到CMD,就不得不提起CommonJS,CommonJS是服务端模块的规范,由于Node.js被广泛认知。
根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的module.exports对象。
1 2 3 4 5 6 7 8 9 10 11 | //file1 .js moudle.exports = { a: 1 }; //file2 .js var f1 = require( './file1' ); var v = f1.a + 2; module.exports ={ v : v }; |
CommonJS 加载模块是同步的,所以只有加载完成才能执行后面的操作。像Node.js主要用于服务器的编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较快,不用考虑异步加载的方式,所以CommonJS规范比较适用。但如果是浏览器环境,要从服务器加载模块,这是就必须采用异步模式。所以就有了 AMD CMD 解决方案。
UMD(Universal Module Definition - 通用模块定义)
UMD又是个什么玩意呢?UMD是AMD和CommonJS的一个糅合。AMD是浏览器优先,异步加载;CommonJS是服务器优先,同步加载。
既然要通用,怎么办呢?那就先判断是否支持node.js的模块,存在就使用node.js;再判断是否支持AMD(define是否存在),存在则使用AMD的方式加载。这就是所谓的UMD。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ((root, factory) => { if (typeof define === 'function' && define.amd) { //AMD define([ 'jquery' ], factory); } else if (typeof exports === 'object' ) { //CommonJS var $ = requie( 'jquery' ); module.exports = factory($); } else { // 都不是,浏览器全局定义 root.testModule = factory(root.jQuery); } })(this, ($) => { //do something... 这里是真正的函数体 }); |
ESM(ECMA Script Modules)
ESM是ES6中的模块化规范,在nodeJS新版本中可以直接使用,现在大部分浏览器也开始支持(在script标签上设置type="module"),
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 写法一 export var m = 1; // 写法二 var m = 1; export { m }; // 写法三 var n = 1; export { n as m }; // 写法四 var n = 1; export default n; // 写法五 if ( true ) { import ( './myModule.js' ). then (({ export1, export2 }) => { /* ... */ }); } // 写法六 Promise.all([ import ( './module1.js' ), import ( './module2.js' ), import ( './module3.js' )]). then (([module1, module2, module3]) => { /* ... */ }); |
Reference
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现