npm依赖版本锁定详解

npm中有一个package-lock.json的文件,即npm依赖锁文件,用来描述npm依赖生成的确切树,这样不管你的依赖有何种更新,都会按照这个确切树来安装使用。

不同的包管理工具对应不同的锁文件:
● npm => package-lock.json
● yarn => yarn.lock
● pnpm => pnpm-lock.yaml

整体上大同小异,本文主要以npm为例。

一、semver 版本控制规范

在软件管理的领域里存在着被称作“依赖地狱”的死亡之谷,系统规模越大,加入的包越多,你就越有可能在未来的某一天发现自己已深陷绝望之中。
为了解决依赖包的版本混乱问题,制定了这个 semver 规范。

版本格式:【主版本号.次版本号.修订号】,版本号递增规则如下:

  1. 主版本号:当你做了不兼容的 API 修改,(不兼容更新)
  2. 次版本号:当你做了向下兼容的功能性新增,(功能新增)
  3. 修订号:当你做了向下兼容的问题修正。(bug修复)
    先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。(例如beta、test版本)

(更详细内容参考官网文档:https://semver.org/lang/zh-CN/)

二、安装依赖时的版本规则

npm依赖规则中,还有 >、>=、<、<=、x、*、-、||、~、^ 等符号。通过在版本号前面加上这些符号,可以有效的限制依赖的版本。

  • version:必须依赖某个具体的版本。如:2.5.2,表示必须安装2.5.2版本。
  • >version:必须大于某个版本。
  • >=version:大于或等于某个版本。
  • <version:必须小于某个版本。
  • <=version:小于或等于某个版本
  • x-range:x的位置可以为任意版本。
  • *-range:任意版本。“”也表示任意版本。
  • version1 - version2:大于等于version1,小于等于version2。
  • range1 || range2:满足range1或者满足range2,可以有多个范围。
  • ~version:大概匹配某个版本。
    • 如果次版本号(Y)指定了,那么次版本号(Y)不变,而修订号(Z)任意。
    • 如果次版本号(Y)和修订号(Z)未指定,那么次版本号(Y)和修订号(Z)任意。
  • ^version:向上兼容某个版本。
    ○ 从版本号最左侧开始,到首个非零数字,这些位置固定,其余位置任意。如果缺少某个位置,则这个位置可以任意。
"~2.5.2" // 表示 >=2.5.2 且 <2.6.0
"~2.5" // 表示 >=2.5.0 且 <2.6.0
"~2" // 表示 >=2.0.0 且 <3.0.0
"^2.5.2" // 表示 >=2.5.2 且 <3.0.0
"^0.1.3" // 表示 >=0.1.3 且 <0.2.0
"^0.0" // 表示 >=0.0.0 且 <0.1.0

使用npm安装依赖时在 package.json 里生成的默认是 ^version 形式,安装时会安装最新的依赖。

  • 这意味着,在多人协作时,如果一个人安装了某个版本,另一个人在安装时这个依赖更新了此版本号,就会安装另一个版本,不同的版本会有差异,可能就会出现问题。
  • 另外在本地构建和服务器构建时可能也会有类似的差异导致问题。

三、依赖锁定

如果所有的node包都严格符合语义化版本(semver)管理的规则,那么npm的最优版本号就能保证所下载的依赖包一定是与代码兼容的。
由于无法保证这一前提,如果想要保证他人下载的依赖包与我们的代码绝对兼容,就需要锁定项目中依赖包的版本号。

1. 写死版本号锁定

最简单的方法,就是指定具体版本号,可以将package.json中版本号开头的 ^ 和 ~ 等标记去掉。
后续安装新的依赖包时,则使用 npm i --save-exact <package_name> 或者 npm i --save <package_name>@1.2.3(指定依赖的具体版本),这样package.json中就不会出现最优版本的标记。

  • 缺陷:无法锁定次级依赖的版本号,即依赖包的依赖包。

2. 锁文件

由于在重新安装依赖时,依赖树模块的版本存在着不确定性,为了解决这个问题,npm提供了 npm-shrinkwrap.json 或 package-lock.json 文件,这两种文件被称为包锁或锁文件。

1)npm shrinkwrap

在npm 5版本以前(不包括npm 5),可以通过执行 npm shrinkwrap 命令,创建一个新的或覆盖已有的 npm-shrinkwrap.json 文件。该文件记录了目前所有依赖包(及更底层依赖包)的版本信息。
当再次运行npm install命令重新安装依赖时,npm首先会找npm-shrinkwrap.json文件,依照其中的信息来准确地安装每一个依赖包,只有当这个文件不存在时,npm才会使用package.json。

  • 每次更新package.json或者node_modules时,如: npm install新包、npm update、npm uninstall等操作,为了保证所有开发人员的资源一致,还是要手动运行npm shrinkwrap更新npm-shrinkwrap.json文件。
  • npm shrinkwrap计算时是根据当前依赖安装的目录结构生成的,如果不能保证package.json文件定义的依赖与node_modules下已安装的依赖是匹配、无冗余的,建议在执行npm shrinkwrap命令前清理依赖并重新安装(rm-rf node_modules&&npm install)或精简依赖(npm prune)。
2)package-lock.json

在npm 5以后,运行npm intall会自动生成一个新文件package-lock.json,其内容跟上面提到的npm-shrinkwrap.json基本一样,在修改pacakge.json或者node_modules时会自动产生或更新它。
当项目中已存在package-lock.json文件,再安装项目依赖时,将以该文件为主进行解析安装指定版本的依赖包,而不是使用package.json来解析和安装。
因为package-lock.json为每个模块及其每个依赖项都指定了版本、位置和完整性哈希,所以它每次创建的安装都是相同的。

  • cnpm并不支持package-lock。 使用cnpm install时,并不会生成package-lock.json文件。即使项目中已有package-lock.json文件,执行cnpm install命令,cnpm 也不会识别,仍会根据package.json安装依赖。因此,尽量避免直接使用cnpm install安装项目的依赖。
3)区别和联系
  • package-lock.json是npm 5的新特性,且不向下兼容,因此如果npm版本是5以下,还是使用npm shrinkwrap命令。
  • package-lock.json和npm-shrinkwrap.json这两个文件的优先级都比package.json高。
    • 同一个项目里,如果不存在这两个文件,在运行npm install或者初始化项目npm init时,会自动生成一个package-lock.json(npm 5及以上)。
    • 如果这两个文件都存在,安装依赖则是依据npm-shrinkwrap.json,而忽略package-lock.json。
    • 如果项目里不存在package-lock.json,运行命令npm shrinkwrap后,会创建一个npm-shrinkwrap.json文件
    • 如果存在package-lock.json,则会将其重命名为npm-shrinkwrap.json。
  • npm-shrinkwrap.json只有在运行npm shrinkwrap命令时才会创建或更新;而package-lock.json会在修改pacakge.json或者node_modules时自动产生或更新。

四、要不要锁

一直以来这都是个有争议的问题。

1. 两种锁的方式:

  • 一是在package.json里对个别依赖写死版本号锁定。
  • 二是通过锁文件对所有依赖都锁定。

2. 个人建议:

  • 当项目的维护可能陷入停滞或者很少更新时,通过锁文件来锁住依赖,保证项目即使过了很长时间依然能稳定跑起来。
  • 当项目和依赖有专门的维护团队来长期维护时,不锁依赖,一般这种依赖的版本更新会比较规范,有问题也能及时发现和修复。
    ○ 如果是个别依赖的维护不稳定,这部分依赖可以通过package.json写死版本号来锁定。

其他情况就需要综合考量了,利弊都有,没有绝对的说法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/56441.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java+SpringBoot+Vue的非物质文化网站的设计与开发

基于JavaSpringBootVue的非物质文化网站的设计与开发 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#…

非线性关卡设计

【GDC】如何设计完全非线性的单人关卡_DOOM (bilibili.com) 本文章算是此视频的简单笔记&#xff0c;更详细还请看视频 设计完全非线性关卡强调自由移动和沙盒式玩法&#xff0c;鼓励玩家进行不可预测的移动和空间探索。讲解者分享了设计此类关卡的具体步骤&#xff0c;包括明…

Linux 命令 chown 和 chmod 的区别

Linux 命令 chown 和 chmod 的区别 chown的作用&#xff1a;更改文件或目录的所有者和所属用户组chmod的作用&#xff1a;更改文件或目录的访问权限 chown的作用&#xff1a;更改文件或目录的所有者和所属用户组 $ chown [options] user:group file_pathuser&#xff1a;新文件…

100个运维工程师必知术语 点赞收藏

网络相关术语 • IDC&#xff08;Internet Data Center&#xff09;&#xff1a;互联网数据中心&#xff0c;提供服务器托管、机柜租用、专线接入等服务。 • ISP&#xff08;Internet Service Prvider&#xff09;&#xff1a;互联网服务提供商&#xff0c;向用户提供互联网接…

清华最新RAG框架:Adaptive-Note RAG,比Adaptive RAG还要好

1. 为什么要提出 Adaptive-Note RAG&#xff1f; RAG&#xff08;检索增强生成&#xff09;技术是一种能有效解决LLM&#xff08;大语言模型&#xff09;幻觉问题的可靠手段&#xff0c;通过借助外部非参数化知识&#xff0c;帮助LLMs拓展其知识边界。 但是&#xff0c;传统R…

解决:gpg: 从公钥服务器接收失败:服务器故障

当你添加密钥时报错&#xff0c;可以按照下面的步骤&#xff0c;依次输入。 # 停止 Network Manager 服务 sudo service network-manager stop# 删除 Network Manager 的状态文件 sudo rm /var/lib/NetworkManager/NetworkManager.state# 重新启动 Network Manager 服务 sudo …

python 爬虫 入门 一、基础工具

一&#xff0c;网页开发者工具的使用 我们可以用 requests 库来从一个url或者说一个网址来爬取资源&#xff0c;这里以百度主页和windows初始浏览器Microsoft Edge为例&#xff0c;我们进入百度主页后按F12进入开发者模式&#xff0c;我们常用的功能是元素和网络&#xff0c;源…

了解Retrofit和Volley这两个网络请求框架

Retrofit和Volley都是Android开发中常用的网络请求框架&#xff0c;它们各自具有独特的特点和适用场景。以下将详细阐述对这两个网络请求框架的了解&#xff0c;包括它们的基本概念、使用方法、优缺点以及适用场景等方面。 一、Retrofit网络请求框架 1. 基本概念 Retrofit是…

word,exl,txt转pdf

有些时候需要上传一些附件&#xff0c;比如exl&#xff0c;word&#xff0c;预览的时候客户需要用pdf展示&#xff0c;下面就简答介绍下转换方法 效果图 依赖&#xff1a; 这是我从网上下载到本地然后再依赖的&#xff0c;也可以使用pom文件依赖更好 代码如下&#xff1a; i…

LeetCode:LCP77.符文储备(排序 Java)

目录 LCP77.符文储备 题目描述&#xff1a; 实现代码与解析&#xff1a; 排序 原理思路&#xff1a; LCP77.符文储备 题目描述&#xff1a; 远征队在出发前需要携带一些「符文」&#xff0c;作为后续的冒险储备。runes[i] 表示第 i 枚符文的魔力值。 他们将从中选取若干符…

qiankun 应用之间数据传递

qiankun 应用之间数据传递 全局共享 initGlobalState qiankun initGlobalState API 单击前往 qiankun 内部提供了 initGlobalState 方法用于注册 MicroAppStateActions 实例用于通信&#xff0c;该实例有三个方法&#xff0c;分别是onGlobalStateChange、setGlobalState、of…

重塑输电线路运维管理,巡检管理系统守护电网稳定运行

在输电线路巡检管理中&#xff0c;一个高效、直接的巡检系统对于确保电力供应的稳定性和安全性至关重要。巡检系统能够直接对接运维需求&#xff0c;减少繁琐流程&#xff0c;并强化数据分析能力&#xff0c;这无疑为输电线路的运维管理带来了诸多优势。以下是对这些优势的具体…

求指导储层饱和度及含水率测井解释

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

缓存穿透/击穿/雪崩(附生产BUG)

优质博文&#xff1a;IT-BLOG-CN 一、背景 为什么要写这篇文章&#xff1f; 生产缓存生成服务转java时&#xff0c;需要通过配置文件进行流量切换。开发人员同时打开了两个配置页面。原配置信息ABCDEF。在第一个配置页面进行缓存切换&#xff0c;添加G业务缓存&#xff0c;配…

Java - Spring 表达式语言 (SpEL) 简单入门

Java - Spring 表达式语言 (SpEL) 简单入门 文章目录 Java - Spring 表达式语言 (SpEL) 简单入门引言一、环境二、资料三、引用SpEL依赖四、SeEL支持的功能基础1&#xff1a;获取对象值基础2&#xff1a;获取对象值基础3&#xff1a;集合对象象的访问基础4&#xff1a;使用SeEL…

各种排序方法总结

目录 1. 冒泡排序 (Bubble Sort 2. 选择排序 (Selection Sort) 3. 插入排序 (Insertion Sort) 4. 快速排序 (Quick Sort) 5. 归并排序 (Merge Sort) 6. 堆排序 (Heap Sort) 排序算法 时间复杂度 空间复杂度 备注冒泡排序 最好情况: O(n) 平均情况: O(n^2) 最坏情况: O(n^…

制冷压缩机液击介绍

液态制冷剂或润滑油随气体吸入压缩机气缸时损坏吸气阀片的现象,以及进入气缸后没有在排气过程迅速排出,在活塞接近上止点时,被压缩而产生的瞬间高液压的现象通常被称为液击。液击可以在很短时间内造成压缩受力件 ( 如阀片、活塞、连杆、曲轴、活塞销等 )的损坏,是往复式压…

Linux:linux系统中目录的遍历

Linux系统中目录的遍历 1、Linux中目录的遍历(1)函数opendir(2)函数readdir(3)函数closedir(4)遍历指定目录的所有文件和子目录 1、Linux中目录的遍历 (1)函数opendir 打开需要被遍历的目录 DIR *opendir(const char *pathname);pathname&#xff1a;待遍历的目录return&#…

国际期货收费行情源CTP推送式/期货配资软件开发对接行情源的技术性说明

在现代金融市场中&#xff0c;期货交易因其高风险和高回报特性而备受关注。为了满足期货交易者的需求&#xff0c;开发高效、稳定和安全的期货交易软件变得尤为重要。本文将对国际期货收费行情源CTP推送式及期货配资软件的开发对接行情源的技术细节进行详细说明。 一、CTP&…

Sequelize 提示报错ERR_HTTP_HEADERS_SENT

ERR_HTTP_HEADERS_SENT 是一个在 Node.js 环境中常见的错误,它通常发生在尝试向一个已经发送了 HTTP 头部的响应对象发送更多头部或数据时。在 Sequelize(一个基于 promise 的 Node.js ORM,用于 Postgres, MySQL, MariaDB, SQLite 和 Microsoft SQL Server 数据库)的上下文…