摘要
一文看懂前端中的AMD、CMD、UMD、ESM和CommonJS 都是什么概念,简单说就是前端代码开发模式中的模块化方式。
先看对比
AMD:
全称是:Asynchronous Module Definition,字面意思理解就是异步化模块定义。
推出时间大约在 2011 年,其主要应用场景是浏览器端。主要特点便是采用异步方式加载模块化代码,代码的加载不影响代码逻辑的有序执行。所有模块化代码会提前加载好,代码逻辑需要用到某个模块时,直接从内存读取。
代表性的三方库就是:requrejs
代码示例:
// 在单独的模块化代码文件中定义模块,例如 module1.js, module2.js
define(["dependency"], function (dependency) {
return moduleName;
})
// 导入模块
require(["module1", "module2"], function (module1, module2) {
//使用导入的模块
});
CMD:
全称是:Common Module Definition, 字面意思理解就是 模块化定义。
推出时间大约在 2012 年,同样是用于浏览器端场景,和AMD类似的需求应用场景,不过它的特点是就近依赖(哪里需要模块,就在哪里引入模块),延迟加载。模块化的代码会在需要用到时才加载,加载完成后继续执行代码,用不到的模块不加载。
代表性的三方库就是:seajs
代码示例:
define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) {
// 等于在最前面声明并初始化了要用到的所有模块
if (false) {
// 即便没用到某个模块 b,但 b 还是提前执行了。**这就CMD要优化的地方**
b.foo()
}
});
CommonJS:
NodeJS是CommonJS规范的主要实践者,它有四个重要的环境变量为模块化的实现提供支持:module
、exports
、require
、global
。实际使用时,用module.exports
定义当前模块对外输出的接口(不推荐直接用exports
),用require
加载模块。
CommonJS用同步的方式加载模块。在服务端,模块文件都存放在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。
UMD:
全称:Universal Module Definition,即 联合模块化定义 或者 通用模块化定义。
它是AMD和CommonJS的一个糅合。AMD是浏览器优先,异步加载;CommonJS是服务器优先,同步加载。UMD做的就是先判断是否支持node.js的模块,存在就使用node.js;再判断是否支持AMD(define是否存在),存在则使用AMD的方式加载。
代码示例:
((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:
即现代化模块化系统,常见提到的ES5
, ES6
, ES2018
等是它的不同年份出的版本。其语法上最大的特点便是引入了import
、export
等关键的导入导出语法,从语法层面实现模块化。让JavaScript的代码具备了更为现代化、标准化的开发规范。
其主要运用于现代浏览器中,也可以在服务器端模块使用
代码示例:
// 导出模块
export default SomeObject;
// 导入模块
import moduleName from "./module";