模块化开发在前端越来越流行,使用 node 和 npm 可以很方便的下载管理项目所需的依赖模块。package.json 用来描述项目及项目所依赖的模块信息。

package-lock.jsonpackage.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 A@1.1.0 来实现升级。

因为 1.1.0 package-lock.json 里记录的 A@1.0.0 是不一致的,因此会更新 package-lock.json 里的 A 的版本为 1.1.0。

B 发布了新版本 1.0.1, 1.0.2, 1.1.0, 此刻如果我们不做操作是不会自动升级 B 的版本的,但如果此刻 A 发布了 1.1.1,虽然并没有升级 B 的依赖,但是如果我们项目里升级 A@1.1.1,此时 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 项目的依赖, B@^1.0.0,package.json如下

{ "dependencies": { "A": "^1.1.0", "B": "^1.0.0" }}
复制代码

我们执行这个操作后,package-lock.json 并没有被改变,因为现在 package-lock.json 里 B@1.1.0 满足 ^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 可能被意外更改的原因

  1. package.json 文件修改了

  2. 挪动了包的位置

将部分包的位置从 dependencies 移动到 devDependencies 这种操作,虽然包未变,但是也会影响 package-lock.json,会将部分包的 dev 字段设置为 true

  1. 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

【总结】1361- package.json 与 package-lock.json 的关系相关推荐

  1. java中将json字符串_Java中JSON字符串与java对象的互换实例详解

    在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好, ...

  2. json java 实例_java JSON数据转对象

    只要电脑配置了JDK, 便可使用Json2Bean, 不用导入到eclipse或android studio, 直接双击就可以打开使用, 每次使用之前要重新设置编辑规则,不用改动什么规则,点" ...

  3. Java构造和解析Json数据之org.json

    一.介绍 org.json包是另一个用来beans,collections,maps,java arrays 和XML和JSON互相转换的包,主要就是用来解析Json数据,在其官网http://www ...

  4. JSON之三:获取JSON文本并解释(以google的天气API为例)

    google提供了天气的api,以广州天气为例,地址为: http://api.openweathermap.org/data/2.5/weather?q=guangzhou 返回的结果为: { &q ...

  5. Android中的JSON解析方式:json; Gson ; Fastjson

    本文主要介绍Json数据的解析 ----a,json数据的介绍 ----b,json数据的解析 ----c,gson数据的解析,谷歌公司的一种格式 ----d,fastjson数据的解析,阿里巴巴的一 ...

  6. android怎么根据标题解析json,如何在android中解析没有json对象标题的json数组?

    首先,我创建了解析器类JSONParser.java package com.example.myparse; import java.io.BufferedReader; import java.i ...

  7. JSON中的JSON.parseArray()方法、JSON.parseObject()方法和JSON.tojsonString()方法

    1.JSON.JSON.parseObject和JSON.toJSONString JSON.parseObject,是将Json字符串转化为相应的对象:JSON.toJSONString则是将对象转 ...

  8. Go Web编程--解析JSON请求和生成JSON响应

    现在无论是网站.App.小程序还是移动端H5页面应用,都是采用前端与后端单独部署,相互之间以API接口交互的形式构建而成的.因为在结合可读性.编码数据大小和开发者使用难度上都JSON格式是一个比较好的 ...

  9. java封装json串示例_Java JSON示例

    java封装json串示例 Welcome to the Java JSON Example Tutorial. JSON (JavaScript Object Notation) is text-b ...

  10. json.parser性能_Jackson JSON Java Parser API示例教程

    json.parser性能 Jackson JSON Java Parser is very popular and used in Spring framework too. Java JSON P ...

最新文章

  1. java接受微信回调_SpringMvc微信支付回调示例代码
  2. “数学不行,干啥也不行!”CTO:基础差的程序员,你不知道有多难!
  3. Black Hat USA 2021主议题介绍
  4. Python基础——min/max与np.argmin/np.argmax
  5. 【红茶原创】-MRTG Install In RedHat AS4
  6. 3DMAX烘焙AO步骤
  7. kettle 数据库密码解密
  8. 用nodejs和vue实现消息盒子
  9. 使用sap BO sap BO报表制作财务三栏明细账
  10. 友华光猫超级密码获取——PT622PT632
  11. Solr Tokenizers分词器介绍
  12. Lifeline功能介绍03——课堂信息的查询
  13. pc、h5微信授权登录
  14. Windows使用三:笔记本打不开wifi
  15. 信息安全系统设计基础实验一
  16. 中国膨润土市场消费状况与投资盈利预测报告(2022-2027年)
  17. 在知乎逮到一个腾讯10年老测试开发,聊过之后收益良多...
  18. 哪些些实验适合用计算机实测,计算机实测物理实验2014年讨论内容
  19. linux操作系统与Windows操作系统
  20. 软件技术基础知识复习

热门文章

  1. 8种隔夜食物千万不要吃
  2. Visual Paradigm简单教程(1):绘制状态机图
  3. 无法解析域名“mirrors.ustc.edu.cn
  4. 任正非谈成功秘诀:28年只对准一个城墙口冲锋
  5. html5中插入样式表方法,如何插入css样式?
  6. 计算机二级主要是学什么,计算机二级考试内容是什么
  7. qq邮箱smtp服务器imap,如何配置电子邮件客户端使用IMAP(QQ邮箱账户) 你需要学习了...
  8. 案例:WLC HA主WLC进入维护模式
  9. ESP8266 AP模式建立服务器
  10. 棋牌游戏开发不可缺少的四大技术支持