前端模块化: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/...

相关推荐
passerby606134 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了41 分钟前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅44 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc