一次性搞懂 NPM 版本号规则
小麦2025年02月26日1754 字
前端朋友一定对包管理器 NPM 以及 package.json 不会陌生。
依赖管理可以说是前端开发过程中的家常便饭。
你是否还只会无脑 npm install --save?
版本号前面的那些符号有什么作用?
代码里写的版本和实际安装的版本一定相同吗?
语义化版本和依赖版本有什么区别?
带着这些疑问,咱们今天一次性搞懂。
另外在视频末尾,我会出给一些测验题目,大家可以试着在评论区里留下自己的答案。
package.json 依赖包的版本号有多种书写方式,比如 NPM 官方文档里给出的示例。
有带各种前缀符号的,有范围约束的,有一个英文单词的,有的甚至可以是一个 URL。
不同的写法会影响包管理器应该从哪里,以什么样的优先级,安装哪个具体版本。
有朋友可能知道一个叫做 Semantic Versioning(即语义化版本)的东西,
但需要注意的是,它并不等同于 package.json 中定义的依赖包版本。
我们首先有必要对这俩做一下区分。
语义化版本规范的原文我放这里了,它的内容看着多但并不复杂。
我让 DeepSeek 帮大家理解一下,
可以看到所有这些版本号都包含三个数字,以及一个可选的后缀。
语义化版本规范中约定了这几件事:
第一,将版本号分成三个部分,主版本、次版本和修订号。
第二,约定了各部分版本号的递增规则,
第三,不稳定版本号的定义。
第四,它们之间的大小关系,或者叫优先级规则。
而这些都是非强制性约定,这也就意味着开发者完全可以不遵守这些规则。
当然不遵守规则也会带来很多坏处,未来有机会我们再细说。
现在让我们回到依赖版本这里。
根据语义化版本规范,无论是 ^3.3.0,3.3.x 还是 next,都不是合法的语义化版本号。
实际上你在 dependencies 中书写的版本号,官方管它叫 "版本范围",并非版本号。
因此后面我们都统一叫版本范围。
OK,区分清楚语义化版本和版本范围的概念后,我们就可以讨论不同版本范围,对实际安装依赖包版本的影响。
首先从最常用的方式入手,当我们用 npm install --save 命令安装一个依赖包,那么它会自动获取当前依赖包最新(latest)的版本号并安装,然后在前面添加 ^ 号。
比如 some-package 这个包的最新版本号是 1.2.0,那么 npm 就会默认安装 ^1.2.0。
这里 ^ 号的含义,是 "锁定" 主版本号,即保持 x 不变,安装 y.z 中的最新版本 …. 吗?
让我来考考大家,假设 some-package 从 1.2.0 升级到了 1.2.1,重新安装会安装 1.2.0 还是 1.2.1 呢?
答案是显然是 1.2.1,这道题没有难度。
假设 some-package 又发了一个新版本 1.2.2-beta.1,那么重新安装会安装 1.2.2-beta.1 吗?
答案是不会。
这里我们需要理解什么是最新版本。
还记得我们之前在语义化版本规范中,提到的 “不稳定版本” 的约定吗?
NPM 会按照语义化版本的规范,将带有后缀的 1.2.2-beta.1 视为不稳定版本,除非依赖方强制指定该版本,否则永远也不会默认安装。
现在我们将代码改为 ^1.2.2-beta.1,这样就能安装这个 “不稳定” 版本了。
假设后续 some-package 又发布了一个新版本 1.2.2-beta.2,那么重新安装会安装 1.2.2-beta.2 这个版本吗?
答案显然是会。因为依赖方已经在代码里声明自己愿意接受不稳定版本了。
到这里你是否已经完全理解了呢?不,你还没有。我们再来看一个例子:
假设 another-package 的最新版本号是 0.2.0,之前你通过 npm install 安装的版本号是 "^0.1.0",那么重新安装时会安装 0.2.0 吗?
答案是不会,还是维持 0.1.0。
WTF,^ 锁的是主版本,0.2.0 明明就满足规则呀,这又是为什么呢?
按照语义化版本的规范,主版本号为 0 也表示它不 "稳定"。
因此,NPM 在安装依赖时,如果发现主版本号为 0,即便我们使用了 ^ 号,也会同时 "锁定" 次版本,等同于使用 ~ 号。
除非手动改成 ^0.2.0 或者 ~0.2.0,否则永远也不会安装最新的 0.2.0。
你看,区区一个版本范围的书写,就牵扯出这么多约定和规范,它不是一个简单的问题。
理解上面的通用规则之后就比较简单了,下面这张表展示了常见版本范围对应的安装规则,可以暂停看看,我就不念了。
像是 TAG(比如 latest、next 等)表示安装被开发者打上了这个标签的某个版本,可能是 1.2.0 也可能是 2.0.0。常用于体验新版本,需要完全信任开发者。
像是 URL(比如 https://,file:// 开头的)都表示从目标位置安装特定版本的包,常用于开发测试。
接下来我列一些测验,看看你是否已经掌握本期视频的核心要点。
左侧是 xmquiz 包的发布历史,请回答右边的每一种版本范围的实际安装版本。
这个包已经发布到 npmjs.com,你可以用这个命令实际测试看看和你思考的是否一致。
也可以把思考过程和答案贴在评论区,和大家交流。
本期我们区分了语义化版本和版本范围两个概念,学习了语义化版本规范的核心内容,以及各类版本范围的安装规则。
我是小麦,一位热爱分享的前端工程师,期待和你分享更多硬核有用的内容。