NPM 的语义版本控制
在发布 NPM 模块新版本时,建议遵循 “语义版本控制” 考虑使用这样的版本号x.y.z
控制,如下所示:
版本号规则:
- 主版本:做了不兼容的 API 修改,不会向前兼容,一般也称为大版本,当项目依赖需要升级到大版本时需要注意。
- 次版本:通常是做了向前兼容的新功能增加,一般也称为小版本。
- 补丁版本:修复现有的一些错误,也是向前兼容的。
在发布 NPM 包时建议从 1.0.0 开始,例如:
- 1.0.0:新产品首次发布。
- 1.0.1:向前兼容的补丁版本,修改第 3 位数。
- 1.1.0:向前兼容增加新特性,增加中间数字,将最后一位置为 0。
- 2.0.0:不向前兼容的更新,增加第一位数字,将第二、三位数置为 0。
语义化版本号的几种表示方法:
^1.1.2
:^
是 NPM 安装后的默认符号,保持高版本不升级,次版本、补丁版本升级到最新,例如:^1.1.2
等价于1.1.2 >= ^1.1.2 < 2.0.0
。(^
表示与版本兼容,但是存在一些场景,比如 1.1.0 兼容版本从最左边的非0版本号算起, 即^1.1.0
表示>=1.1.0 <2.0.0
.^0.0.3
表示>=0.0.3 <0.0.4
)~1.1.3
:波浪符~
只会升级补丁版本,例如:~1.1.3
等价于1.1.3 >= ~1.1.3 <1.2.0
。(~表示约等于版本, 即 如果存在次版本号,则允许修订号为更高版,否则允许次版本号为更高版。人话的意思就是说~1.2.0
存在 次版本号2
, 那么表示为>=1.2.0 <1.3.0
, 即修改修订号;~1.0.0
只有最高版本号, 那么表示>=1.0.0 <2.0.0
, 即修改次版本号)1.1.3
:不加任何符号表示锁定了这个版本,不会进行任何升级。* 或 ""
:*
号或者空字符""
,不会锁定版本,每次都会升级到最新版本,前面提的问题就是这个导致的。1.0.0-alpha.1
:使用 alpha、rc 等标识的表示该版本是一个预发布版本,该版本可能无法满足预期的兼容性需求,正式环境不要用。- 一个非语义话版本号的示例
v1.0.0
:在一些版本控制的系统中通常用 v 表示版本号,例如git tag v1.0.0
,但它并不是语义化版本号。
表达式 | 范围 | 解释 |
---|---|---|
1.2.3 | 1.2.3 | 精确匹配1.2.3版本 |
~1.2.3 | >=1.2.3 <1.3.0 | 将“最右侧”的进行约等 |
~1.0.0 | >=1.0.0 <2.0.0 | |
^1.2.3 | >=1.2.3 <2.0.0 | 将最左侧的非0以下的位数进行兼容 |
^0.0.3 | >=0.0.3 <0.0.4 |
依赖锁定 - 解决版本不一致问题
考虑一个问题,项目第一次添加一个模块的依赖是 ^1.2.3
,过了两周另一个同事需要修这个项目,此时依赖已经更新到 1.3.0
他在重新安装后就会得到最新的版本,这会带来一个问题,每个人得到依赖版本不一致,该如何确保团队成员的依赖版本都是一致呢?
解决依赖版本不一致的问题一种方法是 “固定依赖版本”,但在实际做法中这种很少见,大多数时候没有意识到一个问题 “安全修复”,通过版本号前加 ^ 或 ~ 符号我们可以得到补丁版本错误修复、向前兼容的小版本新功能。
解决依赖版本不一致的另一种方法是通过 lock 文件(NPM 中的 package-lock.json
或 yarn 中的 yarn.lock
)来解决同一个项目团队成员之间依赖版本不一致的问题,在使用 npm 或 yarn 安装之前会先检查 lock 文件上的版本,并来安装它们,有必要将 lock 文件推送至 git 仓库。
如果需要将依赖项更新到指定范围的最新版本,只需要执行 npm update
命令,该命令会遵循语义化版本控制对依赖进行升级,同时也会更新 lock 文件。