pnpm主打的就是一个速度快,节省磁盘空间,本文就来看一下,pnpm为什么能够速度快,节省磁盘空间
背景
前端早期没有包管理的时候,
- 开发人员需要
手动下载、管理和更新项目所需的所有依赖项
。这需要花费大量的时间和精力,容易出错,并且难以跟踪和维护; - 并且
版本控制困难
,很难确保项目的依赖项使用正确的版本,开发人员可能会遇到依赖项版本冲突和兼容性问题,因为手动管理依赖项时很难追踪和控制所使用的特定版本。 - 每个开发者都需要手动下载和配置项目的依赖项,导致了
重复劳动
和可能的错误,特别是在团队合作的项目中。 - 包管理器提供了丰富的开源库和工具生态系统,开发人员可以轻松地从中选择适合自己项目需求的依赖项,如果不使用包管理器,就无法
充分利用这个生态系统,而需要自己编写和维护大量的代码
。
html
<!DOCTYPE html>
<html>
<body>
<!-- 如果没有包管理器 -->
<!-- 开发人员需要手动下载并将外部库的脚本文件d的正确版本通过script引入 -->
<script src="xxx"></script>
<script src="yyy"></script>
// ...
</body>
</html>
于是npm和yarn相继推出,但是npm和yarn有一些明显缺陷
:
1、
npm3以下,node_modules是嵌套结构,多个包之间可能有相同版本的公共依赖,一层层嵌套复制,没有复用,重复安装,浪费磁盘空间
,而且嵌套越深,路径越长,可能会超过windows的最长路径限制
。 安装个axios,项目node_modules结构就是这样:
txt
axios
|- node_modules
|-- follow-redirects
|-- form-data
| |- node_modules
| |-- asynckit
| |-- combined-stream
| | |- node_modules
| | |-- delayed-stream
| |-- mime-types
| |- node_modules
| |-- mime-db
|-- proxy-from-env
2、
npm3+和yarn,node_modules是扁平结构,比如项目只安装个axios,
axios的依赖也被提到最外层的node_modules中,axios的依赖form-data的依赖asynckit也被安装到最外层的node_modules中,这样好处是,相同依赖且版本相同就不会重复安装,一定程度上可以解决路径过长问题。
但是如果版本不同,还是会有嵌套,根据目录结构结算,只会把其中一个版本提升到最外层的node_modules中。
而且可以在项目里面,引入form-data这个包,尽管我并没有安装,在package.json的dependecies中没有显示声明,但是它在最外层的node_modules中,所以可以引入它,这是一个幽灵依赖
问题,要是项目中把axios包删除了,那form-data这个包也被删除,项目就报错了。
所以pnpm应运而生,相对于npm,yarn具有碾压优势,在了解pnpm之前,先了解一下硬链接和软链接。
硬链接、软链接
硬链接(hard link)
就像是一个文件的复制品,但实际上它们共享同一个身份。可以将硬链接看作是一个人的复制品,无论你使用原始文件还是硬链接,它们都代表同一个文件。所以,如果你改变原始文件的名字或属性,硬链接也会相应地改变。
软链接
,也叫符号链接,就像是一个符号或指示牌,它指向另一个文件的位置。可以将软链接看作是一个指向文件的指示牌,可以根据指示牌找到真正的文件。当你访问软链接时,系统会根据指示牌上的路径找到目标文件。桌面快捷方式就是软链接
- 硬链接是文件的复制品,它们共享同一个身份,对其中一个的更改会影响其他链接。
- 软链接是一个指向目标文件的符号,它只是一个文件的引用,对软链接的更改不会影响目标文件。
1、复制文件
磁盘中会再次复制一份,不会互相影响,平时最多的是右键复制,或者ctrl+c,也可以用命令复制,Windows命令 :copy
a.js a.copy.js,Mac命令:cp
a.js a.copy.js
2、文件硬链接
Windows命令:mklink /H b.hard.js b.js
,Mac命令:ln b.js b.hard.js
3、文件软链接
Window命令:mklink c.soft.js c.js
,Mac命令:ln -s c.js c.soft.js
,windows建立软连接需要管理员权限
pnpm的优势
同样,还是只安装一个axios,
不能访问没有声明的依赖
项目最外层node_modules里面只有一个.pnpm
和axios
两个文件,没有把所有依赖包铺平,在项目里面就不能引入其他包了,不存在幽灵依赖问题了
解决嵌套过深,路径过长
所有同版本的依赖包在硬盘仓库地址里面只保存一份,所有依赖包.pnpm里面铺平了,都是从磁盘的仓库地址硬链接
过来的,这个axios还是一个软链接
,指向/.pnpm/axios@1.6.2/node_moduoles/axios
,axios所依赖的三个包在axios@1.6.2/node_moduoles中都是软链接,所有依赖包真正的位置 都在/.pnpm/packageName@version/node_modules/packageName
,也没有嵌套层级过深,路径过长的问题了
节省磁盘空间
axios包、axios的依赖包、依赖包的依赖包,依赖包的依赖包的依赖包,...,都只在硬盘中只存在一份,其余的都是软链接,并且可以跨项目使用同一版本的依赖,比如有3个项目都用了axios@1.6.2这个版本,它在硬盘仓库地址只有一份,然后硬链接到这个3个项目的node_modules的.pnpm里面,这样空间就大大的节省了
安装速度快
使用 npm 时,依赖每次被不同的项目使用,整个包都会重复安装一次。
而使用pnpm时,假如你上一个项目已经使用pnpm安装了axios@1.6.1这个版本到硬盘仓库地址里面,新项目中,你要安装axios@1.6.2,假如这个两个版本中只有axios.js这个文件变动了,那么磁盘中只会重新安装这一个变动文件,然后硬链接到你新项目的.pnpm中,而不会因为仅仅一个文件的改变复制整新版本包的内容。这样既节省空间而且速度也更快。
pnpm 分三个阶段执行安装:
- 依赖解析,pnpm 具有并行安装的能力,可以同时解析获取多个包, 仓库中没有的依赖都被识别并获取到仓库,
- 根据依赖计算出
node_modules
目录结构。 - 链接依赖项。 所有以前安装过的依赖项都会直接从仓库中获取并链接到
node_modules的.pnpm
。
这种方法比传统的三阶段安装过程(解析、获取和将所有依赖项写入node_modules
)快得多。