模块这个概念其实在前端开发中已经见过类似的东西了,比如 import 一个组件、export 一个函数。Node.js 里的模块就是把这个思想搬到了服务器端。
我们用 工具箱 来打个比方,就全明白了。
1. 什么是模块?------ 就是一个功能独立的"工具箱"
想象你要修理一个东西:
- 没有模块:你把所有工具(扳手、螺丝刀、锤子)全堆在一个大桌子上,想用哪个都得翻半天,代码几万行全写在一个文件里,改一行代码都可能碰坏其他地方。
- 有了模块 :每个工具箱只装一类工具。
hammer.js(锤子工具箱):只负责砸钉子。wrench.js(扳手工具箱):只负责拧螺丝。screwdriver.js(螺丝刀工具箱):只负责拆装小零件。
每个工具箱就是一个模块 。
当你需要砸钉子时,就拿"锤子工具箱"出来用;不需要关心扳手里面是怎么写的。
对应到代码:
一个 .js 文件就是一个模块。文件里写什么功能,这个模块就负责什么功能。
2. 为什么需要模块?
| 好处 | 通俗解释 |
|---|---|
| 复用 | 你在项目A写的"日期格式化"工具,直接复制到项目B就能用,不用重写。 |
| 好维护 | 出 bug 了,比如"用户登录失败",你直接去 login.js 模块里找原因,不用在 1 万行代码里搜。 |
| 多人协作 | 你写 user.js,我写 order.js,互不打架,最后组合起来就行。 |
3. Node.js 中的两种模块
① 内置模块(Node.js 自带的,像"官方工具箱")
安装 Node.js 时,它就送你一堆常用工具箱,比如:
fs:操作文件(读、写、删)http:创建 web 服务器path:处理文件路径
怎么用? 直接用 require 拿过来就行,不用安装。
javascript
// 拿官方送的 fs 工具箱
const fs = require('fs');
// 用里面的 readFile 功能读文件
fs.readFile('a.txt', (err, data) => {
console.log(data);
});
② 自定义模块(你自己做的工具箱)
你想写一个"把用户名字变成大写"的功能,不想跟主文件混在一起,就可以新建一个文件 format.js:
javascript
// format.js
function toUpperCaseName(name) {
return name.toUpperCase();
}
// 把这个函数"交出去",让别的文件能用
module.exports = toUpperCaseName;
然后在另一个文件 app.js 里使用它:
javascript
// app.js
const toUpperCaseName = require('./format.js'); // 注意写相对路径
console.log(toUpperCaseName('alice')); // 输出 ALICE
4. 关键的两个语法(记住就行)
| 语法 | 作用 | 类比 |
|---|---|---|
module.exports = 东西 |
把模块里的东西"公开"出去 | 工具箱打开盖子,让别人能拿到里面的工具 |
require('模块名') |
从别处拿一个模块进来用 | 伸手去拿某个工具箱 |
注意:
- 内置模块直接写名字:
require('fs') - 自定义模块要写路径:
require('./myModule.js')
5. 对比你熟悉的前端模块化
| 前端(ES6 模块) | Node.js(CommonJS 模块) |
|---|---|
export default fn |
module.exports = fn |
import fn from './fn.js' |
const fn = require('./fn.js') |
虽然写法不同,但思路一模一样:一个文件一个独立功能,用的时候导入,不用的时候不影响别人。
6. 最后一句人话总结
模块就是一个独立的 JavaScript 文件,它只做一件事,并把自己的功能通过
module.exports交出来,其他文件通过require拿去用。
之前写前端可能一个组件就是一个模块,现在 Node.js 里一个工具函数、一个数据库操作、一组路由都可以是一个模块。学会这个,就已经掌握了组织 Node.js 代码的核心方法。
试着写两个小文件,互相 require 一下,立刻就会了。