一、模块化开发是什么?
想象你正在搭积木。如果所有积木都堆在一起,要找某个特定积木会很困难。模块化开发就像把积木分类放在不同盒子里,每个盒子有明确用途。在JavaScript中,模块化就是把代码拆分成独立文件,每个文件专注做一件事。
以前我们可能把所有函数都写在一个js文件里,现在可以分开管理。比如用户登录功能放user.js,商品展示功能放product.js。这样做的好处是:
- 代码更容易维护
- 避免变量命名冲突
- 可以复用代码
二、CommonJS:老牌模块系统
CommonJS最早是为服务器端设计的,Node.js就是用它来组织代码的。它的特点是:
- 同步加载模块
- 主要用于服务端
- 语法简单直接
示例1:CommonJS基本用法
// 技术栈:Node.js
// 文件: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
示例2:CommonJS导出多个方法
// 文件:utils.js
exports.uppercase = function(str) {
return str.toUpperCase();
};
exports.lowercase = function(str) {
return str.toLowerCase();
};
// 文件:app.js
const { uppercase, lowercase } = require('./utils');
console.log(uppercase('hello')); // 输出"HELLO"
CommonJS的缺点是它采用同步加载,不适合浏览器环境(因为网络请求是异步的)。在Node 14及以后版本中,虽然支持ES6模块,但CommonJS仍然是默认模块系统。
三、ES6模块:现代标准
ES6模块是JavaScript官方标准,特点是:
- 静态加载(编译时确定依赖)
- 支持异步加载
- 浏览器和Node.js都支持
示例3:ES6模块基础
// 技术栈:现代JavaScript
// 文件:math.mjs
export function multiply(a, b) {
return a * b;
}
// 文件:app.mjs
import { multiply } from './math.mjs';
console.log(multiply(2, 3)); // 输出6
示例4:ES6模块的默认导出
// 文件:logger.mjs
// 默认导出
export default function(message) {
console.log(`[LOG] ${message}`);
}
// 文件:app.mjs
import log from './logger.mjs';
log('系统启动'); // 输出"[LOG] 系统启动"
ES6模块支持更灵活的导入方式:
// 重命名导入
import { multiply as mul } from './math.mjs';
// 导入全部
import * as mathTools from './math.mjs';
四、两者对比与选择建议
4.1 语法差异
| 特性 | CommonJS | ES6模块 |
|---|---|---|
| 导出语法 | module.exports/exports | export/export default |
| 导入语法 | require() | import |
| 加载方式 | 同步 | 静态 |
4.2 使用场景建议
选择CommonJS当:
- 开发Node.js应用(特别是旧版本)
- 需要动态加载模块(条件导入)
- 使用大量现有CommonJS生态库
选择ES6模块当:
- 开发前端应用
- 需要tree-shaking优化
- 使用现代框架如React/Vue
- Node.js 14+环境且可以配置type: "module"
4.3 互操作性
在Node.js中可以通过以下方式混用(但不推荐):
// 在ES6模块中引入CommonJS
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const fs = require('fs');
五、实际应用示例
示例5:前端项目中使用ES6模块
// 文件:src/components/Button.js
export default function Button({ text }) {
return <button className="btn">{text}</button>;
}
// 文件:src/App.js
import Button from './components/Button';
function App() {
return <Button text="点击我" />;
}
示例6:Node服务中使用CommonJS
// 文件:server/router.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.send('首页');
});
module.exports = router;
// 文件:server/app.js
const router = require('./router');
app.use('/', router);
六、注意事项
- 文件扩展名:Node.js中ES6模块建议用.mjs后缀,或在package.json设置"type": "module"
- 浏览器兼容性:现代浏览器都支持ES6模块,但需要