AMD和CMD是ES6前浏览器模块化方案,核心区别在于执行时机:AMD依赖前置、加载完才执行工厂函数,CMD工厂函数立即执行、require时才加载依赖。
和
都是
浏览器
端为解决脚本依赖与加载顺序问题而诞生的
异步模块规范
,但它们的设计哲学和执行时机截然不同——不是“谁更好”,而是“谁更适合你的构建链路”。
为什么需要 AMD 和 CMD?
在 ES6
/
成为主流前,浏览器没有原生模块系统。多个
标签手动加载易出错:
– 依赖模块没加载完就执行(
)
– 加载顺序靠人肉维护,一改就崩
– 无法按需加载、无法隔离作用域
于是 RequireJS(推
)和 SeaJS(推
)分别提出标准化方案,目标一致:让模块可声明依赖、可隔离、可异步加载。
的参数写法暴露核心分歧
两者都用全局
定义模块,但参数结构直接体现理念差异:
(RequireJS):依赖数组前置,强制“声明即加载”
(SeaJS):依赖在函数体内按需
,延迟执行
关键区别不在“是否异步”(二者都是异步加载),而在
模块工厂函数何时执行
:
– AMD:依赖全部 ready 后才调用 factory,适合“启动即全量加载”的场景
– CMD:factory 立即执行,
调用时才触发加载,适合“点击才加载某功能”的懒加载逻辑
立即学习
“
Java免费学习笔记(深入)
”;
Comet AI 浏览器
下载 Comet AI 浏览器,体验由 Perplexity AI 驱动的革命性上网方式。内置 AI 助手可实时总结网页、跨标签页对比信息、自动执行任务。告别繁琐操作,让 AI 成为你的浏览副驾,大幅提升研究与工作效率。支持 Windows、macOS、Android 和 iOS。
下载
实际项目中,你大概率不会直接写 AMD/CMD
现代
前端
工程几乎不再手写
,原因很实在:
打包工具(Webpack/Vite)默认以
为输入,自动转译并内联依赖,无需手动
或
(Node.
js
风格)仍常见于服务端或构建脚本,但浏览器运行时需打包转换
RequireJS/SeaJS 已停止维护(RequireJS 最后更新 2020 年,SeaJS 2017 年停更)
真正遗留的老项目若还在用,排查问题要盯住:
–
路径别配错(尤其
和
)
–
中
必须写在 factory 函数内,写在外面会报
容易被忽略的兼容性陷阱
如果你被迫维护一个老 AMD/CMD 项目,这几个点常导致白屏或静默失败:
写成箭头函数 →
绑定失效,
拿不到上下文
AMD 模块里混用
→ RequireJS 不识别,返回
CMD 模块中
和
同时赋值 → SeaJS 以
为准,前者被忽略
路径别名没在
里注册,却写了
→ 报 404,而不是提示“未配置 alias”
历史价值在于理解模块演进逻辑;工程实践上,
+ 构建工具才是今天该投入精力的地方。那些
和
,现在更多是调试时需要读懂的“古代码”。
AMDCMDimportexportReferenceErrorAMDCMDdefine()define()AMDdefine(['./utils', './api'], function(utils, api) {
// 所有依赖已加载完毕,立即执行
return { init: () => utils.log(api.getData()) };
});CMDrequire()define(function(require, exports, module) {
// 此时 utils.js 还没加载
var utils = require('./utils'); // 真到这行才发起请求
var api = require('./api');
exports.init = function() {
utils.log(api.getData());
};
});require()define()ESMrequire([])define()CommonJSrequire.config()baseUrlpathsCMDrequire()require is not defineddefine()thisrequiremodule.exportsundefinedexportsmodule.exportsmodule.exportsrequire.config()require('jquery')ESMdefine([...])require(['x'], ...)