6月2日 01:45

npm 版本号 ^ 和 ~ 有什么区别?SemVer 和 package-lock 详解

npm 用语义化版本(SemVer)管理包版本,package.json 声明版本范围,package-lock.json 锁定精确版本。理解版本范围符号能避免"昨天还好好的今天就挂了"的问题。

语义化版本号

版本号格式:主版本.次版本.补丁版本(Major.Minor.Patch)

  • Patch(1.0.x):Bug 修复,不改变 API
  • Minor(1.x.0):新增功能,向后兼容
  • Major(x.0.0):破坏性变更,不向后兼容

npm install 默认安装最新版本,但 package.json 里记录的是版本范围,不是精确版本。

版本范围符号

精确版本

json
"react": "18.2.0" // 只安装 18.2.0,不安装任何其他版本

插入号 ^(Caret)

json
"react": "^18.2.0" // >=18.2.0 <19.0.0 "lodash": "^4.17.0" // >=4.17.0 <5.0.0

允许 Minor 和 Patch 更新,锁定主版本。最常用的范围符号——npm install react 默认就用 ^

规则:左边第一个非零数字锁定。

  • ^1.2.3>=1.2.3 <2.0.0
  • ^0.2.3>=0.2.3 <0.3.0(0.x 视为开发阶段,次版本也可能破坏兼容)
  • ^0.0.3>=0.0.3 <0.0.4(0.0.x 视为实验阶段,几乎锁定)

波浪号 ~(Tilde)

json
"react": "~18.2.0" // >=18.2.0 <18.3.0

只允许 Patch 更新,锁定主版本和次版本。比 ^ 更保守,适合需要稳定但偶尔接受 bug 修复的场景。

其他范围

json
"react": ">=18.0.0" // 大于等于 18 "react": "18.0.0 - 18.2.0" // 闭区间 "react": "*" // 任意版本(危险,不要用) "react": "latest" // 最新版本(同上,危险) "react": "file:../local-pkg" // 本地路径

package-lock.json 的作用

package.json 声明范围,package-lock.json 锁定精确版本。

json
// package.json "react": "^18.2.0" // 范围:18.2.0 到 18.x.x // package-lock.json "react": "18.2.0" // 实际安装的精确版本

没有 lock 文件时,npm install 每次可能安装不同版本(18.2.0 → 18.3.1),导致团队成员或 CI 环境的依赖不一致。lock 文件保证所有人安装完全相同的版本。

必须把 package-lock.json 提交到 Git。不要把它加入 .gitignore。

版本冲突排查

bash
npm ls react # 查看项目中安装的 react 版本 npm outdated # 列出所有过时的包 npm view react versions # 查看包的所有已发布版本

重复依赖问题(同一个包安装了多个版本):npm dedupe 尝试去重。

save-exact:精确安装

不想用 ^ 范围?配置 npm 默认用精确版本:

bash
npm config set save-exact true # 或在 .npmrc 里加 save-exact=true

之后 npm install react 会写 "react": "18.2.0" 而不是 "react": "^18.2.0"。适合对版本控制严格的团队。

标签:NPM