1. Node.js 模块系统概述
作为一名长期使用Node.js的开发者,我深刻体会到模块系统选择对项目架构的重要影响。Node.js最初采用CommonJS规范作为默认模块系统,但随着JavaScript语言的发展,ES Modules逐渐成为现代JavaScript的标准模块方案。这两种系统各有特点,理解它们的差异和适用场景对于构建可维护的Node.js应用至关重要。
模块系统本质上解决的是代码组织和复用的问题。在Node.js生态中,模块可以是一个文件、一个目录或一个npm包。良好的模块化设计能够提高代码的可读性、可维护性和复用性。CommonJS(简称CJS)和ES Modules(简称ESM)虽然都能实现模块化,但它们在设计理念和实现方式上存在显著差异。
提示:Node.js从v12开始正式支持ES Modules,并在v13.2+版本中提供了稳定的支持。如果你的项目需要同时支持浏览器和Node.js环境,ES Modules会是更好的选择。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CommonJS模块系统详解
2.1 CommonJS的基本语法
CommonJS是Node.js最早采用的模块系统,它的核心思想是通过require函数同步加载模块,通过module.exports或exports对象导出模块内容。这种设计非常适合服务器端环境,因为服务器上的文件I/O操作通常是同步的。
javascript复制// 导出模块
// math.js
function add(a, b) {
return a + b;
}
module.exports = add;
// 或者
exports.add = add;
// 导入模块
// app.js
const add = require('./math');
console.log(add(1, 2)); // 输出3
在实际项目中,我经常使用CommonJS的模块缓存特性来优化性能。当一个模块被首次require时,Node.js会执行该模块的代码并将结果缓存起来。后续的require调用会直接返回缓存的结果,而不会重新执行模块代码。这种机制对于减少重复计算和I/O操作非常有效。
2.2 CommonJS的导出机制
CommonJS提供了几种不同的导出方式,理解它们的区别可以避免常见的陷阱:
- 直接赋值给module.exports:这会替换整个导出对象
javascript复制module.exports = function() { /* ... */ };
- 给exports对象添加属性:这种方式更灵活,可以逐步添加导出内容
javascript复制exports.add = function(a, b) { return a + b; };
exports.subtract = function(a, b) { return a - b; };
- 混合使用:可以同时使用上述两种方式
javascript复制module.exports = { add: function() { /* ... */ } };
exports.PI = 3.14159;
注意:不能直接对exports赋值,因为这会切断exports与module.exports的引用关系。例如
exports = function() {}是无效的。
