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

概述

历史上,JavaScript 一直没有模块(module)体系,只用一个文件来写程序代码,对于开发维护大型的、复杂的项目是极不友好的。

后来,在社区相继推出了 commonJS、AMD、CMD、UMD、ES module 等模块。

模块介绍

CommonJS

推出时间大约在 2009 年。Node.js 选择了 CommonJS 作为其模块系统,从而使其在服务器端得以广泛应用。它的特性是同步加载模块,在服务器端模块文件都存放在本地磁盘,读取非常快,所以这样做不会有问题。但是,在浏览器端,要从服务器端加载模块,若采用同步加载方式会导致性能、体验等问题

javascript 复制代码
// math.js文件:自定义方法
function add(a, b) {
  return a + b;
}
module.exports = {
  add: add,
};

// index.js文件:引用自定义的模块
var math = require("./math");
math.add(1, 2);

AMD(Asynchronous Module Definition)

推出时间大约在 2011 年。其主要应用场景是浏览器端,异步加载模块,与 CommonJS 最大的不同在于,AMD 采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖某些模块的语句均放置在回调函数中。知名的库有 require.js

javascript 复制代码
// 导入模块
require(["module1", "module2"], function (module1, module2) {
  //使用导入的模块
});

// 定义模块
define(["dependency"], function (dependency) {
  return moduleName;
});

CMD(Common Module Definition)

推出时间大约在 2012 年。同样是为了解决浏览器端的模块化问题,CMD 相比 AMD 使用的是依赖就近,延迟执行等特性,写代码的时候哪里使用哪里再引入模块。知名的库有 sea.js

javascript 复制代码
// 定义导出模块 math.js
define(function (require, exports, module) {
  var $ = require("jquery.js");
  var add = function (a, b) {
    return a + b;
  };
  exports.add = add;
});
// 在需要使用的地方就近导入模块
seajs.use(["math.js"], function (math) {
  var sum = math.add(1 + 2);
});

UMD(Universal Module Definition)

推出时间大约在 2013 年。UMD 主要是解决跨平台模块化方案的问题,它合并了 CommonJS 和 AMD 规范,能够兼容各种情况的环境,同时运行在客户端和服务器端,因此被称为是通用的模块定义。当使用 Rollup/Webpack 之类的打包器时,UMD 通常用作备用模块

javascript 复制代码
(function (root, factory) {
  if (typeof define === "function" && define.amd) {
    define(["dependency"], factory);
  } else if (typeof exports === "object") {
    module.exports = factory(require("dependency"));
  } else {
    root.returnExports = factory(root.dependency);
  }
})(this, function (dependency) {
  return {}; //返回值即为定义的模块
});

ES module

推出时间为 2015 年。ES6 或更高版本在语言标准层面上实现了模块功能,解决了 JavaScript 文件无法使用import, export命令,在语法层面上对模块进行了支持,标准化产品,使得 JavaScript 模块化具备了规范性。可以直接运行在现代浏览器中,也可以作为服务器端模块使用

javascript 复制代码
// 导出模块
export default SomeObject;
// 导入模块
import moduleName from "./module";

优缺点对比

模块 优点 缺点
CommonJS 服务器端模块,同步加载,写法简单直观;Node.js选择了CommonJS作为其模块系统,使其在服务端得以广泛应用。 无法直接在浏览器中运行,需通过如Browserify的工具转换;同步加载可能导致性能问题,特别是处理大型、复杂的依赖树时。
AMD 解决了浏览器环境下模块的异步加载问题,特别在处理大型、复杂的依赖树时有较好性能;可以并行加载多个模块。 代码的阅读和书写比较困难
CMD CMD规范和AMD规范类似,但是依赖就近,延迟执行,只需要简单的define函数。 CMD规范和AMD规范类似,非官方标准,需要运行在如Sea.js之类的运行库上。
UMD UMD模块格式被设计成可以在CommonJS和AMD两个最常见的JavaScript模块定义格式之间进行切换;能够在几乎所有的JavaScript运行环境下执行。 UMD的代码结构略显复杂
ES Module ES Module是JavaScript官方标准,出色的静态模块结构使得编译时就能确定模块的依赖关系,也有助于静态分析和Tree Shaking等优化;浏览器原生支持,无需引入库或者构建工具进行转换,使用简便。 一些旧版浏览器并不支持ES Module。

总结

  • 由于ES module的设计思想是尽量的静态化,使得代码可以静态分析和tree shaking等优化,是目前最好的模块化方案
  • UMD 用得很广泛,通常在 ESM 不起作用的情况下用作备用
  • CJS 是同步的,适合服务端
  • AMD/CMD 是异步的,适合用户端

参考文献

es6.ruanyifeng.com/#docs/modul...

dev.to/iggredible/...

相关推荐
用户新19 分钟前
JS事件深度解析四 事件的循环和异步
前端·javascript·事件·event loop
广州灵眸科技有限公司6 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) Easy-Eai编译环境准备与更新
服务器·前端·人工智能·python·深度学习
万少7 小时前
我把 Kimi 接进微信,几分钟做了个随手出图助手
前端
xiaofeichaichai7 小时前
网络请求与实时通道
前端·网络
kTR2hD1qb8 小时前
从 Responses API 到 Chat Completions:一个模型网关的设计复盘
linux·前端
JAVA9659 小时前
JAVA面试-并发篇 05-并发包AQS队列实现原理是什么
java·开发语言·面试
kyriewen9 小时前
浏览器缓存最强攻略:强缓存、协商缓存、CDN、更新策略,一篇搞定
前端·面试·浏览器
持敬chijing9 小时前
Web渗透之SQL注入-联合查询注入-注入点数据类型判断
前端·sql·安全·web安全·网络安全·安全威胁分析
卷帘依旧10 小时前
Web3前端一面
前端