前后端建议统一使用ESM
文章目录
Node.js模块化发展历程与标准对比
一、模块化的意义
1.1 解决的核心问题
- 避免命名冲突
- 更好的依赖管理
- 提高代码可维护性
- 实现代码复用
1.2 没有模块化的问题
// 全局作用域污染示例
var userName = "张三";
var getUserInfo = function() { /*...*/ };
// 其他文件可能会不小心覆盖这些变量
var userName = "李四"; // 变量被覆盖
二、CommonJS规范
2.1 核心特征
- 同步加载
- Node.js默认支持
- 使用require引入,module.exports导出
2.2 实现示例
// math.js - 导出模块
module.exports = {
add: function(a, b) {
return a + b;
},
subtract: function(a, b) {
return a - b;
}
};
// main.js - 导入模块
const math = require('./math');
console.log(math.add(2, 3)); // 输出: 5
三、AMD (Asynchronous Module Definition)
3.1 特点
- 异步加载
- 浏览器端使用
- 依赖前置声明
3.2 代码示例
// 使用 RequireJS 实现AMD规范
define(['jquery', 'lodash'], function($, _) {
// 模块定义
return {
// 导出的方法
processData: function(data) {
// 使用jquery和lodash处理数据
return _.map(data, function(item) {
return $(item).val();
});
}
};
});
四、UMD (Universal Module Definition)
4.1 核心思想
- 通用模块规范
- 兼容CommonJS和AMD
- 适配多环境运行
4.2 模板示例
// UMD模块包装器
(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 {
// 公共方法
method: function() {}
};
}));
五、ES Modules (ESM)
5.1 主要特性
- 静态导入导出
- 支持异步加载
- 官方标准规范
- Tree Shaking支持
5.2 使用方式
// utils.js - 导出模块
export const formatDate = (date) => {
// 日期格式化逻辑
return date.toISOString();
};
export const calculateAge = (birthDate) => {
// 年龄计算逻辑
return new Date().getFullYear() - birthDate.getFullYear();
};
// main.js - 导入模块
import { formatDate, calculateAge } from './utils.js';
// 按需导入,支持Tree Shaking
六、各规范对比
6.1 加载机制
- CommonJS: 同步加载,适合服务器
- AMD: 异步加载,适合浏览器
- UMD: 兼容多环境
- ESM: 支持同步异步,静态分析
6.2 语法差异
// CommonJS
const module = require('./module');
// AMD
define(['./module'], function(module) {});
// ESM
import module from './module';
七、最佳实践建议
7.1 选择标准
- Node.js后端:优先使用CommonJS
- 现代前端:优先使用ESM
- 需要兼容多环境:考虑UMD
- 老旧项目:可能需要AMD
7.2 工程化配置
// package.json配置示例
{
"type": "module", // 启用ESM
"exports": {
// 同时支持CommonJS和ESM
"require": "./dist/index.cjs",
"import": "./dist/index.mjs"
}
}
八、未来发展趋势
8.1 ESM的统一趋势
- 浏览器原生支持
- Node.js增强支持
- 工具链全面支持
8.2 新特性支持
- 动态导入
- 模块命名空间
- 更细粒度的模块控制