前端模块化发展(5):2011~2013 CMD&UMD

30 阅读3分钟

2011~2013 CMD&UMD

CMD

为什么会有 CMD?

背景问题

2009 年 Node.js 出现 → CommonJS 被推广开来。
但是:

  • CommonJS 是同步加载的:
const fs = require('fs');

在服务器上没问题,因为硬盘读文件很快。

  • 但放到浏览器就很糟糕:网络请求是异步的,如果同步加载模块会卡死页面。

于是浏览器端需要异步模块化方案,于是有了 AMD(RequireJS,2010)

AMD 的问题

AMD 采用“依赖前置”:

define(['jquery', 'underscore'], function($, _) {
  return {
    foo: function() { $('#id').show(); }
  };
});
  • 优点:浏览器可异步并行加载依赖。
  • 缺点:写法别扭,和 CommonJS 差别太大,不符合大多数开发者的直觉。
CMD 的出现(2011,SeaJS)

阿里玉伯(淘宝前端)觉得 AMD 写法“不优雅”,所以提出 CMD(Common Module Definition)
特点:

  • 依赖就近:需要哪个模块时再 require,不像 AMD 一开始就写在 define 里。
  • 更接近 CommonJS 的写法,迁移成本低。

例子:

define(function(require, exports, module) {
  var $ = require('jquery');   // 就近引用
  exports.foo = function() {
    $('#id').show();
  };
});

👉 这样更“顺手”,也更适合当时的国情(很多中国团队在用 CommonJS 风格)。


CMD 的原理

  • CMD 依然基于浏览器的 异步加载
  • 但与 AMD 不同,它在 运行时 才解析 require
    • AMD:一开始就知道要加载哪些模块。
    • CMD:代码执行到 require('x') 才去加载。

⚠️ 这导致 性能差异:AMD 可以并行预加载依赖,CMD 可能要多次网络请求。
所以 CMD 更符合开发习惯,但性能略逊色。


UMD

为什么需要 UMD?

问题背景

2011~2013 年,前端生态混乱:

  • Node.js 生态用 CommonJS。
  • 浏览器端一部分项目用 AMD(RequireJS),一部分用 CMD(SeaJS)。
  • 还有一些老项目,直接把 JS 挂到全局变量上(window.jQuery)。

→ 前端库作者很痛苦:写一个库,得写三四个版本。

UMD 的出现(2012 左右)

UMD(Universal Module Definition)不是新规范,而是一种兼容模式写法

例子:

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    // CommonJS
    module.exports = factory(require('jquery'));
  } else {
    // 浏览器全局变量
    root.myLib = factory(root.jQuery);
  }
}(this, function ($) {
  return {
    foo: function() { $('#id').show(); }
  };
}));

👉 这段代码能在:

  • RequireJS (AMD) 下运行
  • Node.js (CommonJS) 下运行
  • 普通浏览器 <script> 全局变量方式下运行

CMD & UMD 的地位

  • CMD:主要在中国流行,依赖 SeaJS。随着 ES6 模块出现逐渐消失。
  • UMD:至今仍然存在,很多经典库(如 Lodash、Moment.js)仍然使用 UMD 打包方式,以便兼容不同环境。

如何看待 CMD & UMD(作为前端工程师)

  1. CMD
    • 历史意义:让模块化更“接地气”,贴近 CommonJS。
    • 学习意义:理解前端模块化演进思路,但不必深入。
  2. UMD
    • 至今还偶尔能遇到(老库或兼容性考虑)。
    • 学习意义:要知道它的存在,能认出那段兼容代码。

总结一下:

  • CMD(2011):对 AMD 的改良,更好写,但性能稍差。
  • UMD(2012):兼容所有模块化规范的“打补丁方案”。
  • 2015 以后:ES Module 出现,AMD/CMD/UMD 逐渐淡出历史舞台。