javascript模块化规范的本质是应对不同环境的技术约束:commonjs面向服务端同步加载,amd/cmd针对浏览器异步需求,esm作为语言级标准实现编译期静态分析与跨平台原生支持。

区分 JavaScript 模块化规范,关键不在语法细节,而在于它们各自要解决什么环境下的什么问题。设计理念决定了加载方式、执行时机、依赖声明位置和运行场景。
CommonJS:为服务端同步执行而生
Node.js 启动时需要快速、确定性地加载全部依赖,不需要考虑网络延迟。CommonJS 的设计理念就是“一次加载、立即执行、结果缓存”。
- require 是同步阻塞调用,适合文件系统 I/O 稳定的服务器环境
- 模块作用域天然隔离,exports/module.exports 明确导出边界
- 依赖在代码顶部集中声明,但实际执行发生在 require 被调用时(运行时解析)
- 不支持浏览器原生运行,需打包工具(如 Webpack)转译或模拟
AMD:为浏览器异步加载而设计
早期浏览器中,脚本加载依赖网络,同步等待会阻塞页面渲染。AMD 的核心理念是“依赖先行声明、异步并行加载、回调驱动执行”。
- define 定义模块时,第一个参数是依赖数组,提前告知哪些资源要异步拉取
- 模块工厂函数在所有依赖就绪后才执行,避免执行时找不到依赖
- 适合多 JS 文件、无构建流程的旧式前端项目(如 RequireJS 场景)
- 依赖关系清晰可分析,但写法冗长,与自然编码顺序不一致
CMD:兼顾可读性与按需执行
CMD 受 CommonJS 启发,但面向浏览器,理念是“就近书写依赖、用时才加载、保持线性阅读感”。
- require 写在 factory 函数内部任意位置,符合直觉:“这里要用 a.js,我就 require 它”
- 依赖不是一开始就发起请求,而是执行到 require 语句时才触发(懒加载倾向)
- Sea.js 实现强调模块独立性和调试友好,但生态影响力弱于 AMD 和 ESM
- 仍属运行时解析,无法做静态分析,不利于 Tree-shaking
ES Module(ESM):语言级静态模块系统
ESM 不是库或工具方案,而是 JavaScript 语言标准的一部分。它的设计理念是“编译期确定依赖、支持静态分析、兼顾服务端与浏览器原生能力”。
- import/export 是静态语法,必须出现在顶层,不能放在 if 或函数里
- 模块图在代码执行前即可构建完成,便于打包优化、循环引用处理、Tree-shaking
- 默认严格模式,自动启用 top-level await,支持动态 import() 实现异步加载
- 现代浏览器和 Node.js 均已原生支持,成为事实上的统一标准
本质上,从 CommonJS 到 ESM 是一条从“运行时约定”走向“编译期契约”的演进路径。每种规范都是对特定阶段技术约束的回应,而 ESM 因其标准化、静态性与跨平台能力,已成为当前不可逆的主流选择。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











