AndreGeng / AndreGeng.github.io

blog repository
1 stars 0 forks source link

如何锁定项目依赖 #56

Open AndreGeng opened 4 years ago

AndreGeng commented 4 years ago
  1. 为什么要锁定项目依赖

我们知道当我们安装一个npm包时,例如:npm i express --save, npm会去registry里寻找当前最新的版本。并往package.json里加入一条记录,e.g. express: "^4.0.1"

这里的npm包都是遵循『语义化版本』的,也就是我们常说的semver, 包的版本由{主版本号}.{次版本号}.{patch版本号}组成,通常情况下,patch版本号的改动是用于bug fix, 次版本号的升级意味着引入了可以向前兼容的新功能,而主版本的改动意味着breaking change.

npm在package.json里指定的版本匹配符"^", 是用来匹配patch release和minor release的,正常情况下是不会有问题的。

但有些情况下会有问题,例如你把之前提交的express: "^4.0.1"传到了git仓库中,当团队的其他成员通过npm install安装依赖时,这时express已经有了一个更新的版本e.g. 4.0.2, 那这位同事就会把4.0.2安装到他的本地,导致每个团队成员都可能在本地有不同的依赖库版本。 当恰巧某一个包的发布没有遵循semver时,或者这个版本引入了一个bug时。 我们就很难去排查这种情况,所以我们希望团队的所有成员运行的项目,都要有相同的依赖版本。

  1. 怎么实现锁定项目依赖版本

大家在把npm升级到5.0以后时,运行npm install命令以后,肯定会发现本地多出了一个package.lock.json文件。 第一反应是不是这玩意是用于锁定项目依赖的,那是不是说明只要我们把package.lock.json也提交到git仓库里,其他同事npm install依赖时就能完全,遵循package.lock.json里指定的版本了。。 然而,并没有那么简单

  1. 争议点

首先,在npm 5.0以前,package.json是包依赖版本的single source of truth. 你只用看一眼package.json里依赖包的版本号就可以了,但有了package.lock.json以后很多用户手动更改package.json里依赖包的版本号,然后运行npm install 会发现依赖包的版本并没有改变。这让很多用户觉得很不合理。。(其实我觉得还挺合理的😂)于是npm仓库里出现了这个issuepackage-lock.json file not updated after package.json file is changed

npm在5.1版本中改变了npm install的运行规则,让package.json重新成为了single source of truth. (按官方的说法,5.1之前的表现是bug, unintended behavior)也就是说5.1版本以后,如果你手动更改了package.json里特定依赖的版本,然后运行npm install命令package.lock.json里锁定的版本会被更改的。 你以为这就完了?nonono, 当你安装了npm 5.3.0版本,没有手动更改package.json的情况下,运行npm install, 你会发现package.lock.json里的版本号被更新了,WTF..参见这个#17979

冷静下。。那么我们期望的行为是怎么样的呢。简单的说就是在没有手动更改package.json的情况下,以package.lock.json为准。当用户手动修改了package.json,则以package.json为准。那npm在哪个版本符合了这个期望呢?目前看下来是v5.6.0(之前看有同学说v5.4.2以后是正常的,但仓库里还有这么个issue#18712), 所以保险起见还是用v5.6.0以后的版本吧