周末花了2天的时间 详细深入梳理了 pnpm, 主要介绍了pnpm 的特点。主要是 why ??? 深入学习一门知识, Fly哥更注重为什么要这么做??有没有更好的解法
和 npm、 yarn 包管理器一样。pnpm 也有缓存目录, 不过他的缓存目录是 全局的, 在pnpm 中称之为 store
那么pnpm store 存放的路劲是在哪里 输入下面命令
pnpm store path
可以得到当前环境下的 pnpm store 目录路径 ,注意 mac 和 windows 其实 对应的 目录是不一样的。 这一点作为开发者我们不需要关心。 那么 pnpm store 中 存放的是什么类型的文件呢???
这里拿我本地的pnpm path 去带搭建实际看下
输入 pnpm store path
得到如下图
然后点击去 看 pnpm store 全局存的到底是啥
上图是我们全局目录下 pnpm 的目录结构。
我们在全局目录里存放的不是 npm 包的源码,而是 hash 文件,这里采用了基于文件内容寻址方案。
简单来说就是文件内容被加密成了 64 位 hash 值,hash 值都是唯一的,如果文件内容不变,hash 值也不会变。
这种全局store 缓存的特性 ,非常适合npm包版本, 这里我举一个例子, 比如 我们常用的 axios 。全局store 安装的 版本是 3.0.1,
在某一次 pnpm install 的时候, 由于package.json 的语义化版本,导致 axios 升级了 3.0.2 其实可能对于他而言 只是 改了一个文件,
那pnpm 在更新全局store 的时候, 对于axios 其他部分的hash 是不变的, 因为 内容没有变化, 只会变动哪些改变的 hash。这个也是 pnpm install 安装快速的原因, 一定程度上,也节省了磁盘空间。
这里我在讲解一个命令
pnpm store prune
他是删除全局store 中未引用的包, 还是上文中的一个问题 axios 从 3.0.1 升级 3.0.2 了 那么对于我们项目来说 3.0.1 的包 是不是属于是 未引用了。
axios 会有这样的情况, 其他的包版本 也会有这样的情况。不定时的清除 未引用的包 , 只要你的磁盘够大,其实这件事本身没有影响。
运行 pnpm store prune
是无害的,对您的项目没有副作用。如果以后的安装需要已经被删除的包,pnpm 将重新下载他们。
最好的做法是 pnpm store prune
来清理存储,但不要太频繁。有时,未引用的包会再次被需要。这可能在切换分支和安装旧的依赖项时发生,在这种情况下,pnpm 需要重新下载所有删除的包,会暂时减慢安装过程。虚拟store
首先我问大家一个问题, 什么是 虚拟store???
虚拟store (前提是使用pnpm 进行前端的项目包管理) 就是 node_modules 中.pnpm 文件夹
OK, 知道了这个是 虚拟store, 虚拟store 解决了什么问题???
这个其实是社区上非常有名的npm 包问题 —— 幽灵依赖
我这里用一句话概括一下, 其实就是 访问了项目中 本不该存在 "dependencies": 中的依赖, 那他为什么可以访问??是因为yarn 会将当前包的 依赖 平铺到 node_modules中, 导致了你在 node_modules 可以访问不属于本项目的依赖 , 这种行为是极具危险性的, 非常的不安全, 不利于稳定生产。
pnpm 的node_modules 结构非常的简单
|-- animate
|-- 各种包...
|-- .bin
|-- .cache
|-- .pnpm
这里有同学会问, pnpm 这样能跑的起来嘛, 主仓库库依赖的其他包在哪里。在这里先给大家讲解一下前置知识, 软连接 和 硬链接的知识
还是有就是我的全局store 我是如何去共享的?? 我在之前我先补充讲解下 操作系统的硬链接 和 软连接
ln 原文件 链接文件
硬链接,只能引用同一文件系统中的文件。它引用的是文件在文件系统中的物理索引(也称为inode)。当移动或者删除原始文件时,硬链接不会被破坏,因为它所引用的是文件的物理数据而不是文件在件结构中的位置。硬链接记录的是目标的inode。
ls -s 原文件 连接文件
符号链接又叫软链接,和原文件不是一个文件。例如Windows的快捷方式,如果原始文件被删除,所有指向它的符号链接也就都被破坏了。符号链接记录的是目标的path。符号链接可以跨越文件系统,也可以为目录建立。软链接有自己的node,是linux特殊文件的一种,作为一个文件,它的数据是它所连接的文件的路径。
下面是我测试的文件
source 是源文件, soft 和 hard 分别 对应着 软连接 和硬链接
我们先看文件大小
在文件大小方面 soft 链接 比 硬链接 更小 毕竟 他是 快捷方式
我们在看 源文件的 incode 以及对应的文件状态
源文件对应的link 是 2 对应的 Inode 是xx
我们在通过Inode 查出当前文件的 硬链接有多少个
看出来确实是 2个。
软硬链接 是 linux 中解决文件的共享使用问题的两个方式,目的也是为了节省磁盘空间。
我这里先直接说结论:
pnpm 对于 项目的 依赖会 直接软连接到 虚拟store 下对应包的版本下, 然后虚拟store 对应版本 会直接硬链接到 全局的pnpm store 下
然后虚拟store 包 依赖的其他版本 会互相之间软连接。
大家直接看下张图
比如我们项目中的 dependcies 依赖的 A 版本的 1.0.0 在node_modules 其实是软连接, 真实的文件其实在 虚拟store 对应的 A
然后A 在从全局的store 做链接, 因为 A 还依赖 C 这个包 C是全局硬链接 然后 在A 这个node_modules 进行软链接。
所以pnpm 还是十分巧妙的。
实际操作一下
这是某个pnpm 项目 我进入node_modules
查看文件状态
ls -ash
所有后面的依赖的都有一个箭头 都是 .pnpm/xxx
说明都是软连接到 虚拟store 去了
值得关注的属性有两个,一个是 Links,表示硬链接个数,一个是 Inode
我们可以通过 Inode 去查询所有的硬链接
find . -inum 8177610
可以看到,在全局 Library/pnpm/store/下对应的文件目录
4 条记录 也对应了 links:4
我们再去看下官网pnpm 包管理器的特点
node_modules
结构,所有被提升的包都可以访问,避免了幽灵依赖问题hoist
的机制,只会提升一个,其他版本则可能会被重复安装喜欢点赞,再看,转发谢谢!
扫描下方二维码,加我微信,看我逗比朋友圈,拉你进gpt前端交流群,一起抱团取暖。