第03章:AI帮我配置了package.json但没有锁定依赖版本

第03章:AI帮我配置了package.json但没有锁定依赖版本

“昨天还能正常运行的 CI,今天失败了——有人发布了一个新的 minor version,引入了一个 breaking change。或者本地开发没问题,部署到服务器上出现了莫名其妙的错误,因为本地 npm install 用的版本和服务器不一样。AI 给你的 package.json 里满是 ^ 前缀,这意味着每次 npm install 都可能装上不同版本。”


ℹ️ 版本说明:本章基于 Node.js v24.16.0 + npm 10.x

3.1 AI默认会生成什么

// AI 通常给你的 package.json(全部用 ^ 前缀)
{
  "dependencies": {
    "express": "^5.0.0",
    "prisma": "^5.22.0",
    "zod": "^3.22.0",
    "pino": "^9.0.0"
  },
  "devDependencies": {
    "typescript": "^5.6.0",
    "eslint": "^9.0.0"
  }
}

^5.0.0 意味着允许安装 >=5.0.0 <6.0.0 的任意版本——每次 npm install 都可能装上不同版本。


3.2 AI通常遗漏的4个坑

⚠️ 坑1:package-lock.json 没有提交到 Git

# 很多人的 .gitignore 里误加了这一行
package-lock.json    # ← 不应该忽略!

# package-lock.json 的作用:
# 锁定所有依赖(包括间接依赖)的精确版本
# 确保所有人 npm ci 都安装完全相同的版本

npm install vs npm ci

  • npm install:读 package.json,安装满足版本范围的最新版,更新 lock 文件
  • npm ci:读 package-lock.json,安装精确版本,lock 文件不存在则报错(CI 环境用这个)

CI 应该用 npm ci,不是 npm install


⚠️ 坑2:依赖版本范围语义混淆

版本号格式:主版本.次版本.补丁版本(major.minor.patch)
  主版本 = 不兼容变更(breaking changes)
  次版本 = 向后兼容的新功能
  补丁版本 = bug 修复

前缀含义:
  ^5.0.0 → >=5.0.0 <6.0.0(允许 minor + patch 升级)
  ~5.0.0 → >=5.0.0 <5.1.0(只允许 patch 升级,更保守)
  5.0.0  → 精确版本(不自动升级)
  *      → 任意版本(危险!)

问题:即使是 minor 升级(^ 允许),也可能引入 breaking changes(发布者没有遵守语义化版本规范的情况并不少见)。


⚠️ 坑3:依赖安全漏洞没有自动检查

# 检查已知安全漏洞
npm audit

# 输出示例:
# 5 vulnerabilities (1 moderate, 3 high, 1 critical)
# Run `npm audit fix` to fix them

# 自动修复(升级到安全版本)
npm audit fix

# 如果有 breaking change 需要手动处理
npm audit fix --force  # 谨慎!可能升级到 major version

# 在 CI 里加入安全检查(有漏洞时 CI 失败)
npm audit --audit-level=high  # 只有 high/critical 时失败

⚠️ 坑4:peerDependencies 冲突导致不明错误

npm install
# npm WARN ERESOLVE overriding peer dependency
# npm WARN While resolving: my-ui-library@1.0.0
# npm WARN Found: react@18.0.0
# npm WARN node_modules/react
# npm WARN   react@"^18.0.0" from the root project

# 这个警告意味着 my-ui-library 要求某个 react 版本,
# 但你安装的版本不完全兼容
# 可能导致运行时的隐蔽错误

解决方案:用 npm ls <package> 查看依赖树,理解版本冲突原因,再决定是否升级或降级。


3.3 更好的提示词

提示词 P01:生产级 package.json 配置

使用时机:为新项目或现有项目配置合理的依赖管理

帮我为一个 Node.js v24.16.0 项目配置生产级 package.json。

项目情况:
- 类型:[REST API / GraphQL API / 命令行工具]
- 框架:[Express 5.x / Fastify 5.x]
- 数据库:[PostgreSQL with Prisma / MongoDB with Mongoose]
- 部署方式:[Docker / PM2 / Kubernetes]

配置需求:

1. 版本锁定策略:
   - dependencies:用 ^ 还是精确版本?什么情况下应该精确锁定?
   - 对安全敏感包(如 crypto 相关):建议用精确版本?
   
2. scripts 配置(生产必备):
   - "start": 生产环境启动命令
   - "dev": 开发环境启动(nodemon/tsx)
   - "build": 如果用 TypeScript,tsc 编译
   - "test": vitest 或 jest
   - "lint": eslint
   - "audit": npm audit --audit-level=high

3. engines 字段(声明 Node.js 版本要求):
   "engines": { "node": ">=24.0.0", "npm": ">=10.0.0" }

4. .npmrc 配置(CI 行为控制):
   save-exact=true  # npm install 时用精确版本(不加 ^)
   engine-strict=true  # Node.js 版本不满足时报错

5. 什么应该放在 devDependencies vs dependencies?
   - TypeScript:devDependencies(编译时用,运行时不需要)
   - eslint:devDependencies
   - 类型定义包(@types/*):devDependencies

给我完整的 package.json 和 .npmrc 示例。

基于 Node.js v24.16.0 + npm 10.x。

提示词 P02:依赖更新策略

使用时机:现有项目的依赖管理和更新计划

帮我为现有 Node.js 项目制定依赖更新策略。

当前问题:
- 很多依赖落后了好几个大版本
- npm audit 显示有高危漏洞
- 不敢随便升级,怕破坏现有功能

更新策略:

1. 先查清楚现状:
   npm outdated    # 查看哪些包有新版本
   npm audit       # 查看安全漏洞
   npx npm-check-updates  # 显示所有可升级版本

2. 优先级排序(建议顺序):
   P0:npm audit 里的 HIGH/CRITICAL 漏洞(立刻修复)
   P1:直接依赖的 patch 升级(风险最低)
   P2:直接依赖的 minor 升级
   P3:major 版本升级(需要仔细阅读迁移指南)

3. 安全升级流程:
   - 每次只升级一个包
   - 升级后运行 npm test(需要有测试)
   - 检查 CHANGELOG / Release Notes

4. 自动化工具:
   - Dependabot(GitHub):自动创建依赖升级 PR
   - Renovate:更灵活的依赖升级配置
   - 如何配置 Dependabot 只自动合并 patch 升级?

5. 如何处理升级到 major 版本?
   - 如何找到迁移指南?
   - 如何用 git bisect 定位是哪次升级引入的问题?

基于 Node.js v24.16.0 + npm 10.x。

提示词 P03:monorepo 依赖管理

使用时机:多个 Node.js 包在同一个仓库里管理

帮我为 Node.js monorepo 配置依赖管理。

工具选择:
- npm workspaces(内置,v7+)
- pnpm workspaces(更快,磁盘空间更省)
- Turborepo(构建缓存)

我的 monorepo 结构:
packages/
  api-server/      ← Node.js Express API
  shared-utils/    ← 共享工具库
  frontend/        ← React 前端

需求:
1. packages/shared-utils 如何被 api-server 引用?(本地包引用)
2. 所有包共用的 devDependencies(eslint、typescript)怎么放?
3. 某个包独有的依赖怎么管理?
4. 如何确保所有包使用相同版本的 react / express(防止版本冲突)?
5. CI 里如何只构建有改动的包(使用 Turborepo 缓存)?

给我:
- 根目录 package.json(workspaces 配置)
- 子包 package.json 示例
- .npmrc 配置
- GitHub Actions 里的 monorepo 构建配置

基于 Node.js v24.16.0 + npm workspaces。

3.4 验收清单

检查项 验证方法 AI辅助
package-lock.json 在 Git 里 git ls-files package-lock.json 从 .gitignore 移除
CI 用 npm ci(不是 npm install) CI 脚本里有 npm ci 用 P01 更新 CI
npm audit 无 HIGH/CRITICAL npm audit --audit-level=high 退出码为0 用 P02 修复漏洞
engines 字段指定 Node.js 版本 package.json 有 engines 字段 用 P01 添加
有 Dependabot 或 Renovate 配置 .github/dependabot.yml 存在 用 P02 配置
.npmrc 有 save-exact 新 install 的包用精确版本 用 P01 配置

3.5 本章小结

如果你只记一件事:把 package-lock.json 提交到 Git,CI 里用 npm ci 而不是 npm installnpm ci 使用 lock 文件安装精确版本,确保每次构建的依赖完全一致——这是"我本地没问题但服务器出错"问题的最常见根因之一。

依赖管理的三个层次

  1. 版本锁定(lock 文件 + npm ci):确保开发、CI、生产安装完全相同的依赖树
  2. 安全扫描(npm audit + Dependabot):定期检查已知漏洞,HIGH/CRITICAL 立刻修复
  3. 依赖更新策略(patch/minor/major 分级处理):patch 自动合并,minor 测试后合并,major 手动迁移

→ 第4章:AI生成的Node.js应用内存泄漏排查