有风塘主
发布于 2024-11-29 / 92 阅读
0
0

前端AMD、CMD、UMD、ESM和CommonJS都是什么

摘要

一文看懂前端中的AMD、CMD、UMD、ESM和CommonJS 都是什么概念,简单说就是前端代码开发模式中的模块化方式。

先看对比

模块

优点

缺点

CommonJS

服务器端模块,同步加载,写法简单直观;Node.js选择了CommonJS作为其模块系统,使其在服务端得以广泛应用。

无法直接在浏览器中运行,需通过如Browserify的工具转换;同步加载可能导致性能问题,特别是处理大型、复杂的依赖树时。

AMD

解决了浏览器环境下模块的异步加载问题,特别在处理大型、复杂的依赖树时有较好性能;可以并行加载多个模块。

代码的阅读和书写比较困难

CMD

CMD规范和AMD规范类似,但是依赖就近,延迟执行,只需要简单的define函数。

CMD规范和AMD规范类似,非官方标准,需要运行在如Sea.js之类的运行库上。

UMD

UMD模块格式被设计成可以在CommonJS和AMD两个最常见的JavaScript模块定义格式之间进行切换;能够在几乎所有的JavaScript运行环境下执行。

UMD的代码结构略显复杂

ESM

ESM/Es Module是JavaScript官方标准,出色的静态模块结构使得编译时就能确定模块的依赖关系,也有助于静态分析和Tree Shaking等优化;浏览器原生支持,无需引入库或者构建工具进行转换,使用简便。

一些旧版浏览器并不支持ES Module。

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规范的主要实践者,它有四个重要的环境变量为模块化的实现提供支持:moduleexportsrequireglobal。实际使用时,用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 等是它的不同年份出的版本。其语法上最大的特点便是引入了importexport 等关键的导入导出语法,从语法层面实现模块化。让JavaScript的代码具备了更为现代化、标准化的开发规范。

其主要运用于现代浏览器中,也可以在服务器端模块使用

代码示例:

// 导出模块
export default SomeObject;
// 导入模块
import moduleName from "./module";

参考

  1. 前端模块化——彻底搞懂AMD、CMD、UMD、ESM和CommonJS

  2. 前端模块化:commonJS、AMD、CMD、UMD、ES module


评论