前提:项目新环境下出现了样式问题,一番调查后发现,是项目之前被改了包的版本,导致项目在新环境自动将包升到最新版本,不同版本的样式文件不一致这才导致问题。
一、package.json 安装树
package.json 里面定义的是版本范围(比如^1.0.0),具体跑npm install的时候安的什么版本,要解析后才能决定,这里面定义的依赖关系树,可以称之为逻辑树(logical tree)。
node_modules文件夹下才是npm实际安装的确定版本的东西,这里面的文件夹结构我们可以称之为物理树(physical tree)。
安装过程中有一些去重算法,所以你会发现逻辑树结构和物理树结构不完全一样。
package-lock.json可以理解成对结合了逻辑树和物理树的一个快照(snapshot),里面有明确的各依赖版本号,实际安装的结构,也有逻辑树的结构。
二、npm 规则发生的三次变化
自npm 5.0版本发布以来,npm i的规则发生了三次变化。
-
npm 5.0.x 版本,不管package.json怎么变,
npm i
时都会根据lock文件下载 -
5.1.0版本后
npm i
会无视lock文件 去下载最新的npm -
5.4.2版本后,package.json 如果和lock文件不同,那么执行
npm i
时npm会根据package中的版本号以及语义含义去下载最新的包,并更新至lock。 如果两者是同一状态,那么执行npm i
都会根据lock下载,不会理会package实际包的版本是否有新。
这些变化其实也是 npm5 上线以来,根据各个用户遇到的问题做出了调整,现在这个版本就是一个比较稳定的规则。
三、package-lock.json 的作用
npm是一个用于管理package之间依赖关系的管理器,它允许开发者在pacakge.json中间标出自己项目对npm各库包的依赖。在首次安装npm各库包的时候会自动生成 package-lock.json。
而 package-lock.json 就是用以记录当前状态下实际安装的各个npm package的具体来源和版本号。
确定了安装包的依赖之后,后续重新安装的时候都会生成相同的依赖,而忽略项目开发过程中有些依赖已经发生的更新。
也就是说,只要有了package-lock.json 文件,项目后续到一个新的机器上、或者新的下载源,只要按照这个package-lock.json所标示的具体版本下载依赖库包,就能确保所有库包与你上次安装的完全一样。以便项目在各个环境的依赖版本都保持一致。
简单的说,package-lock.json 就是确保你项目中的依赖不会在你不知不觉中自动升级。
举个例子
1. 安装antd包
npm i antd@3.20.2
2. 确定版本
package.json 为 { antd:^3.20.2 }
package-lock.json antd 的verion为3.20.2
node_modules antd version3.20.2
3. 删除 node_modules,重新 npm install,antd 版本不变
package.json 为 { antd:^3.20.2 }
package-lock.json antd 的verion为3.20.2
node_modules antd version3.20.2
4. 手动将package.json antd版本改为 {antd: ^3.20.3 }
5. 然后执行npm install,lock文件的antd版本更新
// 如果通过npm i antd@3.20.3 安装的话也会更新lock文件
6. 新的package中的antd版本与package-lock生成时旧的package设置的antd版本不一致
package.lock文件更新,下载antd最新的3.x.x版本(3.x.x版本最高是3.29.20)
package.json 为 { antd:^3.20.3 }
package-lock.json antd 的verion为3.29.20
node_modules antd version3.29.20