一、模块化开发是什么?

想象你正在搭积木。如果所有积木都堆在一起,要找某个特定积木会很困难。模块化开发就像把积木分类放在不同盒子里,每个盒子有明确用途。在JavaScript中,模块化就是把代码拆分成独立文件,每个文件专注做一件事。

以前我们可能把所有函数都写在一个js文件里,现在可以分开管理。比如用户登录功能放user.js,商品展示功能放product.js。这样做的好处是:

  1. 代码更容易维护
  2. 避免变量命名冲突
  3. 可以复用代码

二、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当:

  1. 开发Node.js应用(特别是旧版本)
  2. 需要动态加载模块(条件导入)
  3. 使用大量现有CommonJS生态库

选择ES6模块当:

  1. 开发前端应用
  2. 需要tree-shaking优化
  3. 使用现代框架如React/Vue
  4. 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);

六、注意事项

  1. 文件扩展名:Node.js中ES6模块建议用.mjs后缀,或在package.json设置"type": "module"
  2. 浏览器兼容性:现代浏览器都支持ES6模块,但需要