Node.js: npm 包管理
最后更新:2026-08-26
Alice 刚接手一个新项目,需要添加日期处理库 luxon、HTTP 框架 express,还要配置测试工具 jest。她起初逐个去官网下载 JS 文件手动拷贝到项目里,版本冲突不断,升级更是噩梦。直到同事介绍了 npm——一条命令安装依赖,package.json 记录版本,lock 文件锁住精确版本,团队协作再也没出过"在我机器上能跑"的问题。
你将学到:
- 使用 npm init / install / uninstall 管理项目依赖
- 区分 dependencies 与 devDependencies 及其适用场景
- 理解 package-lock.json 的作用与提交策略
- 掌握 SemVer 语义化版本规则(^ / ~ / >= 等)
- 运用 npm scripts 与 npx 提升开发效率
1. npm init — 初始化项目
(1) 交互式初始化
运行 npm init 会逐项提示填写项目信息,最终生成 package.json。
▶ 示例:交互式创建 package.json
mkdir my-project && cd my-project
npm init
package name: (my-project)
version: (1.0.0)
description: A sample project
entry point: (index.js)
test command: jest
git repository:
keywords:
author: Alice
license: (ISC)
(2) 快速初始化
使用 -y 跳过所有提示,生成默认 package.json。
▶ 示例:跳过提示快速生成
npm init -y
Wrote to /home/alice/my-project/package.json
生成的 package.json 默认内容:
{
"name": "my-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "ISC"
}
2. npm install / uninstall — 安装与卸载依赖
(1) 安装依赖
npm install <package> 将包下载到 node_modules 并写入 package.json。
▶ 示例:安装生产依赖
npm install express
(2) 安装开发依赖
--save-dev(简写 -D)将包记录到 devDependencies,仅用于开发环境。
▶ 示例:安装开发依赖
npm install jest --save-dev
(3) 卸载依赖
npm uninstall 同时删除 node_modules 中的文件和 package.json 中的记录。
▶ 示例:卸载依赖
npm uninstall express
(4) 安装所有依赖
当拉取他人项目后,运行 npm install 即可按 package.json 和 package-lock.json 还原全部依赖。
▶ 示例:还原依赖
npm install
| 命令 | 作用 | 写入字段 |
|---|---|---|
npm install <pkg> |
安装生产依赖 | dependencies |
npm install <pkg> --save-dev |
安装开发依赖 | devDependencies |
npm install <pkg> -g |
全局安装 | 不写入 package.json |
npm uninstall <pkg> |
卸载依赖 | 移除对应字段 |
npm install |
按清单还原所有依赖 | — |
3. dependencies vs devDependencies
(1) 依赖分类
dependencies 记录生产环境必需的包,devDependencies 记录仅开发阶段使用的包。
▶ 示例:package.json 中的依赖分区
{
"dependencies": {
"express": "^4.18.2",
"luxon": "^3.4.4"
},
"devDependencies": {
"jest": "^29.7.0",
"eslint": "^8.56.0"
}
}
(2) 生产安装跳过开发依赖
使用 --production 或设置 NODE_ENV=production 可跳过 devDependencies 安装,减小部署体积。
▶ 示例:生产环境安装
npm install --production
| 对比项 | dependencies | devDependencies |
|---|---|---|
| 用途 | 生产运行必需 | 仅开发/测试使用 |
| 安装命令 | npm install <pkg> |
npm install <pkg> -D |
| 生产安装 | 始终安装 | --production 时跳过 |
| 典型包 | express、luxon、axios | jest、eslint、nodemon |
| 部署要求 | 必须包含 | 可省略 |
4. package-lock.json 的作用
(1) 锁定精确版本
package-lock.json 记录每个依赖的精确版本与完整性哈希,确保所有环境安装结果一致。
(2) 提升安装速度
lock 文件中保存了完整的依赖树,npm 可跳过版本解析直接下载。
▶ 示例:lock 文件片段
{
"node_modules/luxon": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz",
"integrity": "sha512-zaBViHBuQffgP8h...',
"requires": {}
}
}
| 属性 | 作用 |
|---|---|
| version | 精确安装的版本号 |
| resolved | 包的下载地址 |
| integrity | SHA-512 哈希,校验完整性 |
| requires | 该包的子依赖列表 |
5. 语义化版本(SemVer)
(1) 版本号格式
SemVer 格式为 主版本.次版本.补丁版本(MAJOR.MINOR.PATCH),各有不同含义。
(2) 版本范围符号
在 package.json 中用符号约束可接受的版本范围。
| 符号 | 含义 | ^1.2.3 允许范围 |
~1.2.3 允许范围 |
|---|---|---|---|
^ |
兼容次版本 | >=1.2.3 <2.0.0 |
— |
~ |
兼容补丁版本 | — | >=1.2.3 <1.3.0 |
>= |
大于等于 | >=1.2.3 |
— |
> |
大于 | >1.2.3 |
— |
x |
通配 | 1.2.x → >=1.2.0 <1.3.0 |
— |
▶ 示例:不同范围的实际效果
{
"express": "^4.18.2",
"lodash": "~4.17.21",
"axios": ">=1.6.0",
"debug": "4.3.x"
}
(3) 版本更新规则
- PATCH(补丁):修复 bug,不改变 API
- MINOR(次版本):新增功能,向后兼容
- MAJOR(主版本):破坏性变更,不向后兼容
6. 全局安装 vs 本地安装
(1) 本地安装
默认行为,包安装到项目 node_modules,不同项目可使用不同版本。
(2) 全局安装
加 -g 标志,包安装到系统全局目录,提供命令行工具。
▶ 示例:全局安装命令行工具
npm install -g nodemon
(3) 何时使用全局安装
仅安装需要命令行访问的工具(如 nodemon、pm2),项目依赖始终本地安装。
| 对比项 | 本地安装 | 全局安装(-g) |
|---|---|---|
| 安装位置 | 项目 node_modules | 系统全局目录 |
| package.json | 写入依赖记录 | 不写入 |
| 版本隔离 | 项目间独立 | 全局共享同一版本 |
| 适用场景 | 项目运行依赖 | CLI 工具 |
| 卸载命令 | npm uninstall <pkg> |
npm uninstall -g <pkg> |
| 典型包 | express、lodash | nodemon、pm2、typescript |
7. npm scripts
(1) 内置脚本
start 和 test 是 npm 内置脚本,可直接用 npm start / npm test 运行。
(2) 自定义脚本
其他脚本需用 npm run <name> 执行。
▶ 示例:配置常用 scripts
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest --coverage",
"lint": "eslint src/"
}
}
npm start
npm run dev
npm test
npm run lint
(3) 脚本间的钩子
pre<script> 和 post<script> 在目标脚本前后自动执行。
▶ 示例:使用 pre 钩子
{
"scripts": {
"prebuild": "npm run lint",
"build": "node build.js",
"postbuild": "echo Build complete"
}
}
运行 npm run build 会依次执行 prebuild → build → postbuild。
| 脚本 | 执行命令 | 说明 |
|---|---|---|
| start | npm start |
启动应用 |
| test | npm test |
运行测试 |
| dev | npm run dev |
开发模式(自定义) |
| lint | npm run lint |
代码检查(自定义) |
8. npx 命令
(1) 临时执行远程包
npx 可直接执行未安装的包,避免全局污染。
▶ 示例:临时使用 create-react-app
npx create-react-app my-app
(2) 执行本地安装的命令
npx 会优先查找本地 node_modules/.bin,再查找全局,最后远程下载。
▶ 示例:执行本地工具
npx jest
(3) 指定版本执行
▶ 示例:使用特定版本的包
npx express-generator@4 --view=ejs my-site
9. .npmrc 配置
(1) 配置文件层级
.npmrc 支持项目级、用户级、全局级三个层级,优先级从高到低。
▶ 示例:项目级 .npmrc 设置镜像源
registry=https://registry.npmmirror.com
(2) 常用配置项
| 配置项 | 作用 | 示例值 |
|---|---|---|
| registry | 指定下载源 | https://registry.npmmirror.com |
| save-prefix | 默认版本前缀 | ^ 或 ~ |
| prefix | 全局安装路径 | /usr/local |
| cache | 缓存目录 | ~/.npm |
▶ 示例:通过命令设置配置
npm config set registry https://registry.npmmirror.com
npm config get registry
npm config list
10. npm install 执行流程
flowchart TD
A[npm install] --> B{是否存在 package-lock.json?}
B -- 是 --> C[读取 lock 文件中的精确版本]
B -- 否 --> D[解析 package.json 中的版本范围]
D --> E[查询 registry 获取最新满足版本]
E --> F[生成依赖树]
C --> G[下载包到缓存]
F --> G
G --> H[写入 node_modules 目录]
H --> I[更新 package-lock.json]
I --> J[安装完成]
11. 综合示例:从零搭建项目依赖
以下示例演示 Alice 从零创建项目、安装依赖、配置脚本并启动开发服务器的完整流程。
mkdir alice-server && cd alice-server
npm init -y
npm install express luxon
npm install jest nodemon --save-dev
安装完成后的 package.json:
{
"name": "alice-server",
"version": "1.0.0",
"description": "Alice's date-aware HTTP server",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2",
"luxon": "^3.4.4"
},
"devDependencies": {
"jest": "^29.7.0",
"nodemon": "^3.0.2"
},
"license": "ISC"
}
创建入口文件 index.js:
const express = require('express');
const { DateTime } = require('luxon');
const app = express();
const PORT = 3000;
app.get('/', (req, res) => {
const now = DateTime.now().toISO();
res.json({ message: 'Server is running', timestamp: now });
});
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
启动开发服务器:
npm run dev
[nodemon] starting node index.js
Server listening on port 3000
❓ 常见问题
📖 小节
- npm init 初始化项目,-y 跳过提示
- install/uninstall 管理依赖,-D 写入 devDependencies
- package-lock.json 锁定精确版本,必须提交
- SemVer 用 ^/~/>= 控制版本范围
- 全局安装仅用于 CLI 工具,项目依赖一律本地安装
- npm scripts 简化常用命令,start/test 可省略 run
- npx 临时执行远程包,无需全局安装
- .npmrc 按项目/用户/全局三层配置
📝 作业
- 运行
npm init -y创建项目,手动修改 package.json 的 name、description 和 scripts - 安装
express和luxon作为 dependencies,安装jest作为 devDependencies,观察 package.json 变化 - 分别用
npm list和npm outdated查看依赖状态 - 创建
.npmrc文件设置 registry 为https://registry.npmmirror.com,重新安装验证 - 编写一个自定义 script
hello,输出 "Hello from npm scripts",用npm run hello执行