阅读 114

什么是package.json和package-lock.json

1.需求由来

之前,在react项目开发过程中遇到一个问题,同一个项目第一次cnpm install的时候还可以启动,过一段时间,把node_modules删掉,重新cnpm install,发现项目启动报错了。奇怪,项目代码和之前一样,一点都没改动。查其原因,发现是package.json文件的依赖模块版本号没有固定,如 "roadhog": "^2.5.0-beta.4"。这里有个^,安装的时候会安装2.x.x的最新版本,因为这期间该模块有更新,导致两次install的版本不一样,所以项目报错了。

2.解决办法

第一个想到的是我把该模块写死不就行了 "roadhog": "2.5.0-beta.4"。但是仔细一想,仍会有问题。npm最方便的地方,是它可以帮我们管理依赖,自动下载依赖。意思是假如我们依赖roadhog,roadhog又依赖模块A、B等,我们安装roadhog时,npm会自动帮我们安装好roadhog依赖的模块A、B等。

我们把roadhog锁死了,但是其引用的A模块仍用的是^括号写法(即没有锁死版本),所以假如A模块更新了,仍可能会出现之前类似的问题。那么该怎么进行版本控制呢。
所以我们要对整个依赖树做锁定,那前后编译出来的应用版本就不会存在两次安装版本不一的问题了。这就引出了我们的package-lock.json文件。它的产生就是来对整个依赖树进行版本固定的(锁死)

3.package-lock.json定义

引用官方解释:

package-lock.json它会在npm更改node_modules目录树或者package.json时自动生成的,它准确的描述了当前项目npm包的依赖树,并且在随后的安装中会根据package-lock.json来安装,保证是相同的一个依赖树,不考虑这个过程中是否有某个依赖有小版本的更新。
什么意思?我后面会解释,我们先了解下这个文件是如何生成的?

4.package-lock.json生成

  1. 默认,当我们在一个项目中npm install时候(前提该项目有package.json文件),安装完成后,会自动生成一个package-lock.json文件(位置和之前的package.json文件同级)。该文件里面记录了package.json依赖的模块,以及依赖的依赖。并且给每个依赖标明了版本, 获取地址和哈希值, 使得每次安装都会出现相同的结果. 不管你在什么机器上面或什么时候安装。

  2. 当我们下次再npm install时候,npm发现如果项目中有package-lock.json文件,会根据package-lock.json里的内容来处理和安装依赖而不再根据package.json.

  3. 网上说npm版本是v5.0.0以上的版本,但是测试我的版本是5.几(具体忘了),安装的时候并没有生成package-lock.json,于是升级了最新版本(我当时升级的是6.9.0),发现可以了。

     npm -v //查看npm版本
     npm install -g npm //升级npm到最新版本
     npm install -g npm@6.0.1 //升级npm到指定版本
    复制代码
  4. 如果package-lock.json已经生成,我再次更新package.json某个模块版本(包括手动更改package.json某个版本号,然后重新npm install或者类似npm install antd@3.15.0来更新某个模块),package-lock.json都会自动更新到之前设置的版本,所以不用担心package.json更新了,package-lock.json还是旧的问题。npm v5.1.0之前存在该问题,npm v5.1.0以后不存在该问题。此同步功能是作为npm v5.1.0的一部分发布的,该版本于2017年7月5日上线。

5.package-lock.json格式

如果你有浏览它,会发现它长得类似package.json的依赖,但是比它复杂多了。package-lock.json是一个包含你所有依赖的巨大列表, 它包含明确的版本号, 依赖的获取地址, 一个用于验证完整性和正确性的哈希值, 以及这个依赖本身所需要的依赖.截个图看看:

image.png

从图中,我们可以看出里面有很多参数,具体参数解释我们可以参考官方文档

6.cnpm不支持package-lock.json

  1. 使用cnpm install时候,并不会生成package-lock.json文件,网上搜,cnpm维护者似乎并不打算支持该功能,具体大家可以去搜下。
  2. cnpm install的时候,就算你项目中有package-lock.json文件,cnpm也不会识别,仍会根据package.json来安装。所以这就是为什么之前你用npm 安装产生了package-lock.json,后面的人用cnpm来安装,可能会跟你安装的依赖包不一致,这是因为cnpm 不受package-lock.json影响,只会根据package.json进行下载。

npm 5.x 发布以来到现在的5.6.0 lock的作用变更过好多次,

从npm3.x更新到了npm5,但是发现执行 npm i 时的现象跟网络上的科普文不太一致。

有提到不管怎么修改package.json文件,重复执行npm i,npm都会根据lock文件描述的版本信息进行下载。

也有提到重复npm i时,npm会不顾lock的信息,根据package.json中的包Semantic versioning 版本信息下载更新模块(lock貌似没啥用了)。

查阅资料得知,自npm 5.0版本发布以来,npm i的规则发生了三次变化。

1、npm 5.0.x 版本,不管package.json怎么变,npm i 时都会根据lock文件下载

package-lock.json file not updated after package.json file is changed · Issue #16866 · npm/npm

这个 issue 控诉了这个问题,明明手动改了package.json,为啥不给我升级包!然后就导致了5.1.0的问题...

2、5.1.0版本后 npm install 会无视lock文件 去下载最新的npm

然后有人提了这个issue why is package-lock being ignored? · Issue #17979 · npm/npm

控诉这个问题,最后演变成5.4.2版本后的规则。

3、5.4.2版本后 why is package-lock being ignored? · Issue #17979 · npm/npm

大致意思是,如果改了package.json,且package.json和lock文件不同,那么执行npm i时npm会根据package中的版本号以及语义含义去下载最新的包,并更新至lock。

如果两者是同一状态,那么执行npm i 都会根据lock下载,不会理会package实际包的版本是否有新。

文章分类
前端
文章标签