前端模块化的发展历程是怎样的?AMD、CMD、UMD 是什么?

模块化发展历程

全局变量 → IIFE → CommonJS → AMD/CMD → UMD → ES Modules

1. 全局变量(最早期)

// utils.js
var utils = { add: function(a, b) { return a + b } }

// app.js
utils.add(1, 2)

2. IIFE(立即执行函数)

// utils.js
var utils = (function() {
  function add(a, b) { return a + b }
  return { add }
})()

3. CommonJS(Node.js)

// 同步加载,适合服务端
const fs = require('fs')
module.exports = { add: (a, b) => a + b }

4. AMD(Asynchronous Module Definition)

RequireJS 提出的浏览器异步模块规范:

// 定义模块
define('math', [], function() {
  return { add: function(a, b) { return a + b } }
})

// 引入模块
require(['math'], function(math) {
  math.add(1, 2)
})

5. CMD(Common Module Definition)

SeaJS 提出的规范,类似 AMD 但依赖就近:

define(function(require, exports, module) {
  var math = require('math')
  exports.add = function(a, b) { return a + b }
})

6. UMD(Universal Module Definition)

兼容 CommonJS、AMD 和全局变量的通用方案:

(function(root, factory) {
  if (typeof exports === 'object' && typeof module === 'object') {
    // CommonJS
    module.exports = factory()
  } else if (typeof define === 'function' && define.amd) {
    // AMD
    define([], factory)
  } else {
    // 全局变量
    root.MyModule = factory()
  }
})(this, function() {
  return { add: function(a, b) { return a + b } }
})

7. ES Modules(ES6+)

// math.mjs
export function add(a, b) { return a + b }

// app.mjs
import { add } from './math.mjs'

对比总结

规范 加载方式 适用 现状
CommonJS 同步 Node.js 仍在使用
AMD 异步 浏览器 已过时
CMD 异步 浏览器 已过时
UMD 兼容 通用 库的降级
ESM 静态+异步 通用 ✅ 推荐

为什么 ESM 是最终方案

  1. 语言原生支持,不需要库
  2. 静态分析:编译时确定依赖
  3. Tree Shaking:摇除未使用代码
  4. 浏览器原生支持:<script type="module">
  5. Node.js 支持:"type": "module"

同分类其他题目