前端
JavaScript模块化规范 (CommonJS, AMD, UMD, ESM)
本文将简单探讨四种主要的JavaScript模块化规范: CommonJS, AMD, UMD 和 ESM。
1. CommonJS
CommonJS最初是为服务器端JavaScript设计的, 现在在Node.js中广泛使用。
核心概念:
- 每个文件都被视为一个模块
- 使用
require()
函数导入模块 - 使用
module.exports
或exports
导出模块
示例:
// math.js
function add(a, b) {
return a + b;
}
module.exports = {
add: add
};
// main.js
const math = require('./math');
console.log(math.add(2, 3)); // 输出: 5
工作原理:
require()
函数同步加载模块- 模块在第一次被
require
时执行,之后缓存结果 - 模块代码在本地作用域中执行,不会污染全局作用域
2. AMD (Asynchronous Module Definition)
AMD设计用于浏览器环境, 支持异步加载模块。
核心概念:
- 使用
define()
函数定义模块 - 使用
require()
函数加载模块
示例:
// math.js
define([], function() {
return {
add: function(a, b) {
return a + b;
}
};
});
// main.js
require(['math'], function(math) {
console.log(math.add(2, 3)); // 输出: 5
});
工作原理:
define()
函数定义模块,可以指定依赖require()
函数异步加载模块及其依赖- 所有依赖加载完成后,执行回调函数
3. UMD (Universal Module Definition)
UMD旨在创建同时兼容AMD和CommonJS的模块。
核心概念:
- 通过判断运行环境来决定使用哪种模块系统
- 可以在浏览器和Node.js中使用
示例:
(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.returnExports = factory(root.jQuery);
}
}(this, function($) {
return {
// 模块方法
};
}));
工作原理:
- 检测当前环境支持的模块系统
- 根据环境使用相应的模块定义方式
- 允许同一模块在不同环境中使用
4. ESM (ECMAScript Modules)
ESM是JavaScript的官方标准模块系统, 在现代浏览器和Node.js中得到支持。
核心概念:
- 使用
import
语句导入模块 - 使用
export
语句导出模块 - 支持静态分析, 允许树摇优化
示例:
// math.js
export function add(a, b) {
return a + b;
}
// main.js
import {
add
} from './math.js';
console.log(add(2, 3)); // 输出: 5
浏览器中使用设置 type="module":
<script type="module" src="main.js"></script>
工作原理:
- 模块在编译时静态解析
- 导入和导出在文件顶层进行
- 模块只执行一次,结果被多个导入共享
总结
目前来将,ESM (ECMAScript Modules) 和 CommonJS 是现在使用最广泛的两种模块化方案。 前端开发正在逐渐向ESM过渡, 因为它是官方标准, 且支持Tree Shaking。 后端开发(Node.js)也在慢慢采用ESM, 但由于历史原因, CommonJS仍然广泛使用。