当前位置:网站首页>【总结】1361- package.json 与 package-lock.json 的关系
【总结】1361- package.json 与 package-lock.json 的关系
2022-06-25 07:20:00 【pingan8787】
模块化开发在前端越来越流行,使用 node 和 npm 可以很方便的下载管理项目所需的依赖模块。package.json 用来描述项目及项目所依赖的模块信息。
那 package-lock.json 和 package.json 有啥关系和联系呢?
package.json
管理包
大家都知道,**package.json 用来描述项目及项目所依赖的模块信息。**,就是帮我们管理项目中的依赖包的,让我们远离了依赖地狱。
通过 npm 管理,使用一些简单的命令,自动生成package.json, 安装包依赖关系都由package.json来管理,我们几乎不必考虑它们。
语义版本控制
首先我们先来了解下依赖包的版本号的定义
版本号由三部分组成:major.minor.patch,主版本号.次版本号.修补版本号。
例如:1.2.3,主要版本1,次要版本2,补丁3。
补丁中的更改表示不会破坏任何内容的错误修复。次要版本的更改表示不会破坏任何内容的新功能。主要版本的更改代表了一个破坏兼容性的大变化。如果用户不适应主要版本更改,则内容将无法正常工作。
安装依赖包的版本如何指定
相信大家都会经历过,我们安装一些依赖包的时候,版本号前面都会带 ^ 或者 ~ 的符号,这两个符号代表什么意思呢?
~ 会匹配最近的小版本依赖包,比如 ~1.2.3 会匹配所有 1.2.x 版本,但是不包括 1.3.0
^ 会匹配最新的大版本依赖包,比如 ^1.2.3 会匹配所有 1.x.x 的包,包括 1.3.0,但是不包括 2.0.0
* 安装最新版本的依赖包,比如 *1.2.3 会匹配 x.x.x,
那么该如何选择呢?当然你可以指定特定的版本号,直接写1.2.3,前面什么前缀都没有,这样固然没问题,但是如果依赖包发布新版本修复了一些小bug,那么需要手动修改package.json文件;~ 和 ^ 则可以解决这个问题。
但是需要注意 ^ 版本更新可能比较大,会造成项目代码错误,所以 建议使用 ~ 来标记版本号,这样可以保证项目不会出现大的问题,也能保证包中的小bug可以得到修复。
版本号写 *,这意味着安装最新版本的依赖包,但缺点同上,可能会造成版本不兼容,慎用!
多人开发时依赖包安装的问题
看了上面版本号的指定后,我们可以知道,当我们使用了 ^ 或者 ~ 来控制依赖包版本号的时候 ,多人开发,就有可能存在大家安装的依赖包版本不一样的情况,就会存在项目运行的结果不一样。
我们举个例子:
假设我们中安装了 vue, 当我们运行安装 npm install vue -save 的时候,在项目中的package.json 的 vue 版本是 vue: ^3.0.0, 我们电脑安装的vue版本就是 3.0.0 版本,我们把项目代码提交后,过了一段时间,vue 发布了新版本 3.0.1,这时新来一个同事,从新 git clone 克隆项目,执行 npm install安装的时候,在他电脑的vue版本就是 3.0.1了,因为^只是锁了主要版本,这样我们电脑中的vue版本就会不一样,从理论上讲(大家都遵循语义版本控制的话),它们应该仍然是兼容的,但也许 bugfix 会影响我们正在使用的功能,而且当使用vue版本3.0.0和3.0.1运行时,我们的应用程序会产生不同的结果。
大家思考思考,这样的话,不同人电脑安装的依赖版项目,是不是都有可能不一样,就会导致每个人电脑运行的应用程序产生不同的结果。就会存在bug的隐患。
这时也许有同学想到,那么我们在package.json上面锁死依赖包的版本号不就可以了? 直接写 vue: 3.0.0锁死,这样大家安装vue的版本都是3.0.0版本了。
这个想法固然是不错的,但是你只能控制你自己的项目锁死版本号,那你项目中依赖包的依赖包呢?你怎么控制限制别人锁死版本号呢?
为了解决这个不同人电脑安装的所有依赖版本都是一致的,确保项目代码在安装所执行的运行结果都一样,这时 package-lock.json 就应运而生了。
package-lock.json
package-lock.json 是在 npm(^5.x.x.x)后才有,中途有几次更改
介绍
官方文档是这样解释的:package-lock.json 它会在 npm 更改 node_modules 目录树 或者 package.json 时自动生成的 ,它准确的描述了当前项目npm包的依赖树,并且在随后的安装中会根据 package-lock.json 来安装,保证是相同的一个依赖树,不考虑这个过程中是否有某个依赖有小版本的更新。
它的产生就是来对整个依赖树进行版本固定的(锁死)。
当我们在一个项目中npm install时候,会自动生成一个package-lock.json文件,和package.json在同一级目录下。package-lock.json记录了项目的一些信息和所依赖的模块。这样在每次安装都会出现相同的结果. 不管你在什么机器上面或什么时候安装。
当我们下次再npm install时候,npm 发现如果项目中有 package-lock.json 文件,会根据 package-lock.json 里的内容来处理和安装依赖而不再根据 package.json。
注意,使用
cnpm install时候,并不会生成package-lock.json文件,也不会根据package-lock.json来安装依赖包,还是会使用package.json来安装。
package-lock.json 生成逻辑
简单描述一下 package-lock.json 生成的逻辑。假设我们现在有三个 package,在项目 lock-test中,安装依赖A,A项目面有B,B项目面有C
// package lock-test
{ "name": "lock-test", "dependencies": { "A": "^1.0.0" }}
// package A
{ "name": "A", "version": "1.0.0", "dependencies": { "B": "^1.0.0" }}
// package B
{ "name": "B", "version": "1.0.0", "dependencies": { "C": "^1.0.0" }}
// package C
{ "name": "C", "version": "1.0.0" }
复制代码在这种情况下 package-lock.json, 会生成类似下面铺平的结构
// package-lock.json
{
"name": "lock-test",
"version": "1.0.0",
"dependencies": {
"A": { "version": "1.0.0" },
"B": { "version": "1.0.0" },
"C": { "version": "1.0.0" }
}
}
复制代码如果后续无论是直接依赖的 A 发版,或者间接依赖的B, C 发版,只要我们不动 package.json, package-lock.json 都不会重新生成。
A 发布了新版本 1.1.0,虽然我们 package.json 写的是 ^1.0.0 但是因为 package-lock.json 的存在,npm i 并不会自动升级,
我们可以手动运行 npm i [email protected] 来实现升级。
因为 1.1.0 package-lock.json 里记录的 [email protected] 是不一致的,因此会更新 package-lock.json 里的 A 的版本为 1.1.0。
B 发布了新版本 1.0.1, 1.0.2, 1.1.0, 此刻如果我们不做操作是不会自动升级 B 的版本的,但如果此刻 A 发布了 1.1.1,虽然并没有升级 B 的依赖,但是如果我们项目里升级 [email protected],此时 package-lock.json 里会把 B 直接升到 1.1.0 ,因为此刻^1.0.0的最新版本就是 1.1.0。
经过这些操作后 项目 lock-test 的 package.json 变成
// package
lock-test{ "dependencies": { "A": "^1.1.0" }}
复制代码对应的 package-lock.json 文件
{
"name": "lock-test",
"version": "1.0.0",
"dependencies": {
"A": { "version": "1.1.0" },
"B": { "version": "1.1.0" },
"C": { "version": "1.0.0" }
}
}
复制代码这个时候我们将 B 加入我们 lock-test 项目的依赖, [email protected]^1.0.0,package.json如下
{ "dependencies": { "A": "^1.1.0", "B": "^1.0.0" }}
复制代码我们执行这个操作后,package-lock.json 并没有被改变,因为现在 package-lock.json 里 [email protected] 满足 ^1.0.0 的要求
但是如果我们将 B 的版本固定到 2.x 版本, package-lock.json 就会发生改变
{ "dependencies": { "A": "^1.1.0", "B": "^2.0.0" }}
复制代码因为存在了两个冲突的B版本,package-lock.json 文件会变成如下形式
{
"name": "lock-test",
"version": "1.0.0",
"dependencies": {
"A": {
"version": "1.1.0",
"dependencies": {
"B": { "version": "1.1.0" }
}
},
"B": { "version": "2.0.0" },
"C": { "version": "1.0.0" }
}
}
复制代码因为 B 的版本出现了冲突,npm 使用嵌套描述了这种行为
我们实际开发中并不需要关注这种生成的算法逻辑,我们只需要了解,package-lock.json 的生成逻辑是为了能够精准的反映出我们 node_modules 的结构,并保证能够这种结构被还原。
package-lock.json 可能被意外更改的原因
package.json 文件修改了
挪动了包的位置
将部分包的位置从 dependencies 移动到 devDependencies 这种操作,虽然包未变,但是也会影响 package-lock.json,会将部分包的 dev 字段设置为 true
registry 的影响
经过实际使用发现,如果我们 node_modules 文件夹下的包中下载时,就算版本一样,安装源 registry 不同,执行 npm i 时也会修改 package-lock.json
可能还存在其他的原因,但是 package-lock.json 是不会无缘无故被更改的,一定是因为 package.json 或者 node_modules 被更改了,因为 正如上面提到的 package-lock.json 为了能够精准的反映出我们 node_modules 的结构
开发的建议
一般情况下 npm install 是可以的,他能保证根据 package-lock.json 还原出开发时的 node_modules。
但是为了防止出现刚刚提到的意外情况,除非涉及到对包的调整,其他情况下建议使用 npm ci 来安装依赖,会避免异常的修改 package-lock.json,
持续集成工具中更推荐是用 npm ci,保证构建环境的准确性,npm i 和 npm ci 的区别 可以参考官方文档 npm-ci
参考文章:
我的package-lock.json被谁改了?
npm install 生成的package-lock.json是什么文件?有什么用?
作者:阿离王
链接:https://juejin.cn/post/7078233610683170824
边栏推荐
- Prepare these before the interview. The offer is soft. The general will not fight unprepared battles
- Hyper-v:Hyper-v 第 1 代或第 2 代虚拟机
- 在二叉树(搜索树)中找到两个节点的最近公共祖先(剑指offer)
- Use Adobe Acrobat pro to resize PDF pages
- What about the exponential smoothing index?
- 双周投融报:资本埋伏Web3基础设施
- 软件确认测试有什么作用?确认测试报告的价格是多少?
- After using the remote control of the working machine, problems occurred in the use of the local ROS, and the roscore did not respond
- TrendMicro:Apex One Server 工具文件夹
- Data preprocessing: discrete feature coding method
猜你喜欢

GPU calculation

Measure the current temperature

linux中的mysql有10061错误怎么解决

Establish open data set standards and enable AI engineering implementation

Prepare these before the interview. The offer is soft. The general will not fight unprepared battles

A solution to slow startup of Anaconda navigator

leetcode. 13 --- Roman numeral to integer

Data preprocessing: discrete feature coding method

Scanpy (VII) spatial data analysis based on scanorama integrated scrna seq

Data-centric vs. Model-centric. The Answer is Clear!
随机推荐
tp5与tp6的区别是啥呀?
With the beauty of technology enabled design, vivo cooperates with well-known art institutes to create the "industry university research" plan
UEFI:修复 EFI/GPT Bootloader
软件测试月薪10K如何涨到30K,只有自动化测试能做到
CVPR 2022 oral 2D images become realistic 3D objects in seconds
Hyper-v:Hyper-v 第 1 代或第 2 代虚拟机
以科技赋能设计之美,vivo携手知名美院打造“产学研”计划
iframe简单使用 、获取iframe 、获取iframe 元素值 、iframe获取父页面的信息
The difference between personal domain name and enterprise domain name
Summary of NLP data enhancement methods
[thesis study] vqmivc
Deep learning series 48:deepfaker
使用apt-get命令如何安装软件?
Jdbc-dao layer implementation
Bluecmsv1.6-代码审计
想要软件测试效果好,搭建好测试环境是前提
【操作教程】TSINGSEE青犀视频平台如何将旧数据库导入到新数据库?
面试前准备好这些,Offer拿到手软,将军不打无准备的仗
EasyPlayer流媒体播放器播放HLS视频,起播速度慢的技术优化
Incluxdb time series database