Skip to content

主流模块规范对比

以下是主流前端模块规范(CommonJS、AMD、CMD、ES Modules)的对比分析,从语法、适用场景、特性等维度展开:

一、核心语法对比

规范导入语法导出语法特点
CommonJSconst module = require('module')module.exports = valueexports.key = value同步加载,适用于服务器端(Node.js)
AMDrequire(['module'], callback)define(['dep'], function(dep) { return {} })异步加载,依赖前置
CMDdefine(function(require, exports) { const dep = require('dep') })exports.key = value异步加载,依赖就近
ES Modulesimport { name } from 'module'import('./module').then(...)export const name = 'value'export default value静态分析,支持 Tree-shaking

二、关键特性对比

特性CommonJSAMDCMDES Modules
加载方式同步(阻塞)异步(非阻塞)异步(非阻塞)静态(编译时)+ 动态(运行时)
适用环境服务器端(Node)浏览器端浏览器端浏览器 + 服务器(需配置)
依赖声明位置顶部集中声明定义时声明使用时声明顶部集中声明 + 动态导入
执行时机导入时执行定义时执行使用时执行静态分析,按顺序执行
动态导入支持不支持支持支持支持(import('./module')
Tree-shaking不支持不支持不支持支持(静态结构特性)
循环依赖处理允许但需谨慎较复杂较简单支持(按执行顺序)

三、典型场景对比

场景最佳选择规范原因
Node.js 应用CommonJS 或 ES ModulesNode.js 原生支持 CommonJS,通过配置支持 ES Modules
浏览器单页应用ES Modules + 打包工具(Webpack/Vite)现代浏览器原生支持,打包工具优化加载性能
浏览器异步加载AMD(RequireJS)或动态导入需异步加载大量模块时使用
库开发ES Modules + Rollup利用 Tree-shaking,生成精简代码
兼容多环境UMD(通用模块定义)同时支持 CommonJS、AMD 和全局变量

四、示例代码对比

1. CommonJS

javascript
// math.js
const add = (a, b) => a + b;
module.exports = { add };

// main.js
const math = require("./math.js");
console.log(math.add(1, 2)); // 3

2. AMD(RequireJS)

javascript
// math.js
define(function () {
  const add = (a, b) => a + b;
  return { add };
});

// main.js
require(["math"], function (math) {
  console.log(math.add(1, 2)); // 3
});

3. CMD(SeaJS)

javascript
// math.js
define(function (require, exports, module) {
  const add = (a, b) => a + b;
  exports.add = add;
});

// main.js
define(function (require, exports, module) {
  const math = require("./math"); // 依赖就近声明
  console.log(math.add(1, 2)); // 3
});

4. ES Modules

javascript
// math.js
export const add = (a, b) => a + b;

// main.js
import { add } from "./math.js";
console.log(add(1, 2)); // 3

// 动态导入
async function loadMath() {
  const { add } = await import("./math.js");
  console.log(add(3, 4)); // 7
}

五、兼容性与生态系统

规范原生支持环境打包工具支持生态成熟度
CommonJSNode.js(默认)Webpack、Rollup、Browserify
AMD需 RequireJS 等库Webpack、Rollup
CMD需 SeaJS 等库部分支持(如 Webpack)
ES Modules现代浏览器、Node.js(需配置)Webpack、Vite、Rollup高(未来趋势)

六、选择建议

  1. 新项目

    • 优先使用 ES Modules(浏览器 + Node.js),配合 Vite 或 Webpack 打包。
    • 若需兼容旧浏览器,使用 Babel 转译。
  2. Node.js 项目

    • 若无需兼容旧版本 Node,直接使用 ES Modules(通过 type: "module" 配置)。
    • 若需兼容,继续使用 CommonJS
  3. 浏览器异步加载场景

    • 优先使用 ES Modules 动态导入,而非 AMD。
  4. 库开发

    • 使用 ES Modules 编写,通过 Rollup 打包为多种格式(ES、CommonJS、UMD)。
  5. 兼容多环境

    • 使用 UMD 格式,或通过打包工具输出多种格式。

七、总结

规范优势劣势适用场景
CommonJS简单直接,Node.js 原生支持同步加载,不适合浏览器Node.js 应用
AMD异步加载,适合浏览器语法复杂,生态逐渐式微legacy 浏览器项目
CMD依赖就近,灵活控制加载时机生态小众,工具支持有限特定场景(如 SeaJS 历史项目)
ES Modules语言标准,静态分析,Tree-shaking需打包工具支持,旧浏览器不兼容现代前端应用与库开发

随着 ES Modules 的普及,未来模块化将趋向统一,建议优先掌握 ES Modules,并了解 CommonJS 以应对 Node.js 场景。

Released under the MIT License.