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的对比

相关推荐
CC码码15 分钟前
告别杂乱数字:用 Intl.NumberFormat 打造全球友好的前端体验
前端·javascript·面试
妮妮喔妮25 分钟前
Webpack和Vite优化的区别
前端·webpack·node.js
广州华水科技1 小时前
单北斗GNSS在大坝形变监测中的应用与性能分析
前端
等风来不如迎风去1 小时前
【web】页面透明、插入图片
前端
谢尔登1 小时前
a 标签的跳转机制
前端·javascript·webpack·node.js
狂炫冰美式1 小时前
当硅基神明撞上人类的“叹息之墙”:距离证明哥德巴赫猜想,AI还有多远?
前端·算法·架构
毕设源码-邱学长1 小时前
【开题答辩全过程】以 基于Vue的爱心公益募捐平台的设计与实现为例,包含答辩的问题和答案
前端·javascript·vue.js
IT_陈寒1 小时前
Redis实战精要:5种高频使用场景与性能优化全解析|得物技术
前端·人工智能·后端
Hilaku2 小时前
那个把代码写得亲妈都不认的同事,最后被劝退了🤷‍♂️
前端·javascript·代码规范
南囝coding2 小时前
Node.js 原生功能狂飙,15 个热门 npm 包要失业了
前端·后端