Node.js: npm 包管理

最后更新:2026-08-26

Alice 刚接手一个新项目,需要添加日期处理库 luxon、HTTP 框架 express,还要配置测试工具 jest。她起初逐个去官网下载 JS 文件手动拷贝到项目里,版本冲突不断,升级更是噩梦。直到同事介绍了 npm——一条命令安装依赖,package.json 记录版本,lock 文件锁住精确版本,团队协作再也没出过"在我机器上能跑"的问题。

你将学到

1. npm init — 初始化项目

(1) 交互式初始化

运行 npm init 会逐项提示填写项目信息,最终生成 package.json

▶ 示例:交互式创建 package.json

BASH
mkdir my-project && cd my-project
npm init
TEXT 📖 仅展示
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

▶ 示例:跳过提示快速生成

BASH
npm init -y
TEXT 📖 仅展示
Wrote to /home/alice/my-project/package.json

生成的 package.json 默认内容:

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

▶ 示例:安装生产依赖

BASH
npm install express

(2) 安装开发依赖

--save-dev(简写 -D)将包记录到 devDependencies,仅用于开发环境。

▶ 示例:安装开发依赖

BASH
npm install jest --save-dev

(3) 卸载依赖

npm uninstall 同时删除 node_modules 中的文件和 package.json 中的记录。

▶ 示例:卸载依赖

BASH
npm uninstall express

(4) 安装所有依赖

当拉取他人项目后,运行 npm install 即可按 package.jsonpackage-lock.json 还原全部依赖。

▶ 示例:还原依赖

BASH
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 中的依赖分区

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 安装,减小部署体积。

▶ 示例:生产环境安装

BASH
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 文件片段

JSON
{
  "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

▶ 示例:不同范围的实际效果

JSON
{
  "express": "^4.18.2",
  "lodash": "~4.17.21",
  "axios": ">=1.6.0",
  "debug": "4.3.x"
}

(3) 版本更新规则



6. 全局安装 vs 本地安装

(1) 本地安装

默认行为,包安装到项目 node_modules,不同项目可使用不同版本。

(2) 全局安装

-g 标志,包安装到系统全局目录,提供命令行工具。

▶ 示例:全局安装命令行工具

BASH
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) 内置脚本

starttest 是 npm 内置脚本,可直接用 npm start / npm test 运行。

(2) 自定义脚本

其他脚本需用 npm run <name> 执行。

▶ 示例:配置常用 scripts

JSON
{
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest --coverage",
    "lint": "eslint src/"
  }
}
BASH
npm start
npm run dev
npm test
npm run lint

(3) 脚本间的钩子

pre<script>post<script> 在目标脚本前后自动执行。

▶ 示例:使用 pre 钩子

JSON
{
  "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

BASH
npx create-react-app my-app

(2) 执行本地安装的命令

npx 会优先查找本地 node_modules/.bin,再查找全局,最后远程下载。

▶ 示例:执行本地工具

BASH
npx jest

(3) 指定版本执行

▶ 示例:使用特定版本的包

BASH
npx express-generator@4 --view=ejs my-site


9. .npmrc 配置

(1) 配置文件层级

.npmrc 支持项目级、用户级、全局级三个层级,优先级从高到低。

▶ 示例:项目级 .npmrc 设置镜像源

INI
registry=https://registry.npmmirror.com

(2) 常用配置项

配置项 作用 示例值
registry 指定下载源 https://registry.npmmirror.com
save-prefix 默认版本前缀 ^~
prefix 全局安装路径 /usr/local
cache 缓存目录 ~/.npm

▶ 示例:通过命令设置配置

BASH
npm config set registry https://registry.npmmirror.com
npm config get registry
npm config list


10. npm install 执行流程

100%
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 从零创建项目、安装依赖、配置脚本并启动开发服务器的完整流程。

BASH
mkdir alice-server && cd alice-server
npm init -y
BASH
npm install express luxon
npm install jest nodemon --save-dev

安装完成后的 package.json

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

JAVASCRIPT
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}`);
});

启动开发服务器:

BASH
npm run dev
TEXT 📖 仅展示
[nodemon] starting node index.js
Server listening on port 3000

❓ 常见问题

Q package-lock.json 需要提交到 git 吗?
A 需要。它锁定精确版本和完整性哈希,保证团队和 CI 环境安装结果一致。
Q node_modules 需要提交到 git 吗?
A 不需要。体积巨大且可由 npm install 还原,应加入 .gitignore。
Q ^1.2.3 和 ~1.2.3 有什么区别?
A ^ 允许次版本更新(>=1.2.3 <2.0.0),~ 只允许补丁更新(>=1.2.3 <1.3.0)。
Q npx 和 npm exec 有什么区别?
A npm exec 是 npm v7+ 提供的等价命令,功能一致,npx 更简短且兼容旧版。
Q 如何查看已安装包的版本?
A npm list 查看本地依赖树,npm outdated 检查哪些包有更新。
Q npm install 失败提示 EACCES 权限错误怎么办?
A 避免使用 sudo,推荐通过 npm config set prefix 将全局目录设为用户可写路径。
Q dependencies 里的包在生产环境会被安装吗?
A 会。npm install 默认安装 dependencies,加 --production 才跳过 devDependencies。

📖 小节


📝 作业

  1. 运行 npm init -y 创建项目,手动修改 package.json 的 name、description 和 scripts
  2. 安装 expressluxon 作为 dependencies,安装 jest 作为 devDependencies,观察 package.json 变化
  3. 分别用 npm listnpm outdated 查看依赖状态
  4. 创建 .npmrc 文件设置 registry 为 https://registry.npmmirror.com,重新安装验证
  5. 编写一个自定义 script hello,输出 "Hello from npm scripts",用 npm run hello 执行
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏