2023-12-13 浅谈pnpm

什么是幻影依赖

我们知道npm、yarn安装依赖包的时候是平铺的结构,如下图:

疑问:明明我package.json文件里只声明了express一个包,为啥有这么多的包被安装到node_modules目录中?

原因其实也都知道,是express这个包又依赖了其他的包,所以就一起安装进来了

那幻影依赖顾名思义就是没有在package.json文件里声明的依赖又出现在了node_modules目录中,这些依赖在生产版本中可能会造成影响

比如在文件中使用了lodash这个库,但是没有在package.json里声明这个依赖,这个依赖就是上述说的幻影依赖

一般会造成两个问题

一个是版本问题:

项目中声明了A库版本v1,A依赖于B库版本v1,这时候项目直接使用了B库(B库没有声明是幻影依赖);下一次升级A库到v2时候,依赖的B库也可能会升级到v2,这时候项目中使用的还是B库v1的版本,造成代码莫名其妙的报错,这种问题还不好排查,等到发生的时候再排查问题就大了

除了版本问题外,另外的一个问题是依赖丢失的问题:

如果A库是开发依赖,则导致在开发环境使用幻影依赖B库没有问题,但是一旦部署的时候就会导致生产环境没有安装开发依赖,使得B依赖丢失,则项目中使用的这个库找不到了,就会在生产环境上报错,那问题大了

解决方法

发现幻影依赖的本质原因后,解决方法也很简单

一种方法就是直接安装这个幻影依赖,这种做法直接有效,但是有个缺陷,就是有时候项目太大了,安装的依赖包太多了,开发人员不会一一去排查包是否是幻影依赖,会直接使用vscode中的智能提示,但是这种智能提示是根据在node_modules中是否有这个库去显示的,这时候就需要一种工具,提示在package.json中没有声明的依赖,你在代码中使用就要报错,马上提示这个库要安装

经常说的依赖关系树其实是一个依赖图结构,如上左侧所示

而把依赖安装过后,到文件系统中又变成文件树结构如上图中间所示,这种方式最早的时候就是npm用的文件方式这样会有重复文件

后来npm升级后以及yarn出现后就会把依赖安装成上图右边所示,扁平结构,这里就造成了幻影依赖了

使用pnpm

pnpm工具的出现完美的解决了上述问题,使用pnpm安装包后,会出现上图中间和右边所示的关系

首先会有个仓库形式的store,这里存储的是所有的安装包以及其依赖包,中间图所示的还是各个依赖之间的关系,不过是以符号链接-即软连接的方式存储的,实际指向的是store中的文件地址

使用pnpm安装的包,在package.json里未声明的包在node_modules下是找不到的,这样在项目中引入就不会有提示,还会报错,上图右边的小箭头指的就是符号链接也就是软连接,真正的包地址是在./node_modules/.pnpm/express@4.18.2/node_modules/express,express的依赖包又被软连接到.pnpm/node_modules目录下

硬连接:是指向文件或者目录的实际物理位置的直接引用,硬连接创建一个新的文件入口,但不创建新的文件内容,它与原始文件共享相同的inode(文件的唯一标识符)和数据块,因此,对硬连接的任何操作都会直接影响原始文件,删除原始文件或硬连接中的任何一个都不会导致数据丢失,只要至少还有一个硬连接存在

软连接(符号链接):是一种特殊类型的文件,包含了对另外一个文件或目录的引用,类似于快捷方式,软连接不直接指向文件的物理位置,而是通过文件路径名来引用目标文件或目录,当访问软连接时,操作系统会自动将其解析为目标文件或目录,删除软连接不会影响原始文件或目录的存在,但如果目标文件或目录被删除,软连接将变为无效

在pnpm中,默认情况下,使用软连接(符号链接)将项目的直接依赖添加到根目录下的node_modules文件夹下,而.pnpm目录中保存的直接和间接依赖的硬连接

下图是pnpm、npm、yarn的对比

相关推荐
黄尚圈圈29 分钟前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水1 小时前
简洁之道 - React Hook Form
前端
正小安4 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch5 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光5 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   5 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   5 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web5 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常5 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇6 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器