Node.js 入门二:模块化与 npm 包管理,学会就能搭项目
一、模块化:让代码像搭积木一样灵活
想象一下,写代码就像搭积木:把一个大项目拆成多个小文件(模块),每个模块负责一件事,用的时候拼起来。这就是模块化。
1. 为什么要用模块化?
- 方便复用:比如写一个 “时间格式化” 的功能,拆成模块后,所有项目都能直接用。
- 避免混乱:每个模块里的变量、函数只在自己内部有效(模块作用域),不会污染全局。
- 好维护:改一个功能只需要改对应的模块,不用动整个项目。
2. Node.js 的模块分类
Node.js 里有 3 种模块,用require()命令就能加载:
| 模块类型 | 来源 | 例子 | 加载方式 |
|---|---|---|---|
| 内置模块 | Node.js 官方提供 | fs(操作文件)、path(处理路径) | require(‘fs’) |
| 自定义模块 | 自己写的.js 文件 | myModule.js | require(‘./myModule’)(必须加./或…/) |
| 第三方模块 | 别人写的工具包 | moment(格式化时间) | 先下载,再require(‘moment’) |

注意
- 使用require()方法加载其它模块时,会执行被加载模块中的代码。
- 使用require()方法加载自定义模块时,可省略文件的后缀名
1. 什么是模块作用域?
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
好处:
防止了全局变量污染的问题
2. 如何共享模块里的内容?
模块里的东西默认 “私有”,想给其他模块用,需要主动 “暴露” 出去。
方法 1:用module.exports暴露
// 新建一个自定义模块:tools.js
const sayHello = () => {
return "Hello from tools!";
};
// 暴露成员(可以是变量、函数、对象)
module.exports = {
sayHello,
version: "1.0.0"
};
方法 2:用exports简化(和module.exports默认指向同一个对象)
// tools.js
exports.add = (a, b) => a + b;
exports.sub = (a, b) => a - b;
加载并使用模块
// 加载自定义模块tools.js
const tools = require('./tools');
console.log(tools.sayHello()); // 输出:Hello from tools!
console.log(tools.add(2, 3)); // 输出:5
注意:require()加载模块时,得到的是module.exports指向的对象(exports只是它的快捷方式)。
4. Node.js中的模块化规范
Node.js遵循了CommonJS模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖。
CommonJS规定:
- 每个模块内部,
module变量代表当前模块。 - module变量是一个对象, 它的
exports属性(即module.exports)是对外的接口。 - 加载某个模块,实是加载该模块的
module.exports属性。require()方法用于加载模块。
二、npm:Node.js 的 “应用商店”
当你需要现成的功能(比如格式化时间、处理 Excel),不用自己写,直接用别人做好的 “包”(第三方模块)。npm就是管理这些包的工具(Node.js 自带,不用额外安装),是全球最大的开源库生态系统,包含超过200万个可重用代码包。
1. 常用 npm 命令
| 命令 | 作用 |
|---|---|
| npm init | 初始化项目 |
| npm i 包名 | 安装包(记录到dependencies,开发和上线都用) |
| npm i 包名 -D | 安装开发依赖(只在开发时用,记录到devDependencies) |
| npm uninstall 包名 | 卸载包 |
| npm i | 从package.json恢复所有依赖(比如拿到别人的项目时) |
| npm i 包名@版本号 安装指定版本 | (比如npm i moment@2.22.2) |
| npm list | 查看已安装包 |
2. 基本用法:安装和使用包
步骤 1:初始化项目(生成package.json)package.json是项目的 “说明书”,记录项目的名称、版本号、描述等以及用了哪些包。新建项目文件夹,打开终端执行:
npm init -y # 快速生成package.json(-y表示默认配置)
包管理文件package.json
{
"name": "my-project",
"version": "1.0.0",
"description": "示例项目",
"main": "index.js",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
- dependencies:生产环境依赖(项目运行时需要)
- devDependencies:开发环境依赖(仅开发时需要)
注意:package.json文件相当于maven的pom.xml
步骤 2:安装包(以格式化时间的moment为例)
npm install moment # 安装最新版
# 简写:npm i moment
安装开发依赖
npm install eslint --save-dev
# 或简写
npm i eslint -D
安装后会多两个东西:
- node_modules:存放下载的包(不用手动改)。
- package-lock.json:记录包的详细信息(版本、下载地址等)。
注意:程序员不要手动修改node_modules或 package-lock.json文件中的任何代码,npm包管理工具会自动维护它们。
步骤 3:使用包
// 导入moment包
const moment = require('moment');
// 格式化当前时间
const now = moment().format('YYYY-MM-DD HH:mm:ss');
console.log(now); // 输出:2024-08-07 15:30:00
3. 解决下包慢的问题
默认从国外服务器下载,速度慢?切换到淘宝镜像:
# 查看当前镜像源
npm config get registry
# 切换到淘宝镜像
npm config set registry=https://registry.npm.taobao.org/
也可以安装nrm工具快速切换镜像:
npm i nrm -g # 全局安装nrm
nrm ls # 查看所有镜像源
nrm use taobao # 切换到淘宝镜像
4. 包的分类
- 项目包:安装在当前项目的
node_modules里,只给当前项目用。- 核心依赖(dependencies):上线后还需要(比如moment)。
- 开发依赖(devDependencies):只开发时用(比如代码检查工具eslint)。
- 全局包:安装在电脑全局目录,所有项目都能用(一般是工具类,比如nrm)。
npm i 包名 -g # 全局安装 npm uninstall 包名 -g # 全局卸载
三、模块加载机制:Node.js 怎么找模块?
当你用require('xxx')时,Node.js 会按以下规则找模块,优先级从高到低:
- 先查缓存:模块加载过一次后会缓存,下次直接用(提高速度)。
- 再找内置模块:比如require(‘fs’),直接加载 Node.js 自带的fs。
- 然后找自定义模块:
- 必须带
./或../(比如require(‘./tools’))。 - 没写扩展名时,会依次尝试
.js、.json、.node。
- 必须带
- 最后找第三方模块:
从当前项目的node_modules里找,找不到就去上层目录的node_modules找,直到根目录。
四、实战:创建和使用自定义模块
1. 创建工具模块
// stringUtils.js
module.exports = {
// 首字母大写
capitalize: str => str.charAt(0).toUpperCase() + str.slice(1),
// 反转字符串
reverse: str => [...str].reverse().join('')
};
2. 使用工具模块
// main.js
const { capitalize, reverse } = require('./stringUtils');
console.log(capitalize('hello')); // "Hello"
console.log(reverse('world')); // "dlrow"
3. 安装并使用第三方包
npm install lodash
// 使用lodash
const _ = require('lodash');
const numbers = [1, 2, 3, 4, 5];
console.log(_.shuffle(numbers)); // 随机打乱数组
五、最佳实践
1. 模块拆分原则:
- 一个模块只做一件事
- 保持模块小而专一
- 避免循环依赖
2. 包管理技巧:
-
使用语义化版本:
主版本.次版本.补丁版本 -
定期更新依赖:npm outdated + npm update
-
添加.gitignore文件:
node_modules/ .env
3. 项目结构示例:
my-project/
├── node_modules/ # 第三方依赖
├── src/ # 源代码
│ ├── utils/ # 工具模块
│ ├── services/ # 服务模块
│ └── index.js # 入口文件
├── package.json # 项目配置
└── README.md # 项目说明
总结:核心要点
- 模块化:拆分成小文件,用
module.exports暴露,require()加载,避免全局污染。 - npm:管理第三方包的工具,
npm i安装,package.json记录依赖,淘宝镜像加速下载。 - 加载机制:缓存→内置模块→自定义模块→第三方模块,按这个顺序找模块。
更多推荐

所有评论(0)