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

相关推荐
亚里士多没有德7752 分钟前
强制删除了windows自带的edge浏览器,重装不了怎么办【已解决】
前端·edge
micro2010145 分钟前
Microsoft Edge 离线安装包制作或获取方法和下载地址分享
前端·edge
.生产的驴10 分钟前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
awonw13 分钟前
[前端][easyui]easyui select 默认值
前端·javascript·easyui
老齐谈电商15 分钟前
Electron桌面应用打包现有的vue项目
javascript·vue.js·electron
九圣残炎34 分钟前
【Vue】vue-admin-template项目搭建
前端·vue.js·arcgis
柏箱1 小时前
使用JavaScript写一个网页端的四则运算器
前端·javascript·css
TU^1 小时前
C语言习题~day16
c语言·前端·算法
一颗花生米。4 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式