精读《pnpm》
ascoders opened this issue · 17 comments
为什么源文件删除之后,对于硬连接的形式没有影响而只对软连接的形式有影响呢,按照您的文章的理解的话,源文件删除了,那么硬连接指针指向的源文件地址就没有源文件了,那就找不到东西了。
为什么源文件删除之后,对于硬连接的形式没有影响而只对软连接的形式有影响呢,按照您的文章的理解的话,源文件删除了,那么硬连接指针指向的源文件地址就没有源文件了,那就找不到东西了。
硬链接和”源文件“是相同的指向结构,可以认为硬链接就是源文件的(副本)。删除其中任意一个时,操作系统检查该数据还有一个链接引用,于是就不会删除源数据,而只是删除链接 inode。
这就好比 js 里面的变量引用,你可以把一个变量赋值给很多变量,gc 的时候如果检查数据还有引用,那么就不会清楚数据源。
我其实有点好奇,pnpm的内容寻址是怎么实现的,.pnpm-store 下存储的是,以文件内容hash后得到的地址,怎么diff虽然我也很好奇,但我更疑惑怎么关联或者说读取呢?
比如我在项目A装了 baz@1.0.0 这时store下有了对应的hash标识的文件
这时我在项目B也想装 baz@1.0.0,但我在下载前并不知道 文件对应的 内容,那应该也不知道文件对应的hash吧?如果每次都是重新下载感觉似乎不太友好?
哦哦,那其实“源文件”也并非磁盘存储处,也只是一个指针的意思吧
哦哦,那其实“源文件”也并非磁盘存储处,也只是一个指针的意思吧
是的。
- 源文件 (inode 1) --> 磁盘块1
- 硬链接1 (inode 2) --> 磁盘块1
- 硬链接2 (inode 3) --> 磁盘块1
- 软连接 (inode 4) ---> 源文件(inode 1)
当删除 “源文件” 时 “磁盘块1” 因为还有 inode 2/3 的引用,所以操作系统不会清除 “磁盘块1”。
但是因为 inode1 被删除了,所以软连接 inode4 的指向就失效了,虽然软连接本身(inode4)依然存在,但是读取数据(inode1 以及数据块1)会失败。
所以不能放弃本地这个概念 直接从网络上使用吗
一个前端项目node_nodules 500M+源码 简直恐怖如斯
哦哦,那其实“源文件”也并非磁盘存储处,也只是一个指针的意思吧
是的。
- 源文件 (inode 1) --> 磁盘块1
- 硬链接1 (inode 2) --> 磁盘块1
- 硬链接2 (inode 3) --> 磁盘块1
- 软连接 (inode 4) ---> 源文件(inode 1)
当删除 “源文件” 时 “磁盘块1” 因为还有 inode 2/3 的引用,所以操作系统不会清除 “磁盘块1”。 但是因为 inode1 被删除了,所以软连接 inode4 的指向就失效了,虽然软连接本身(inode4)依然存在,但是读取数据(inode1 以及数据块1)会失败。
@waitingsong 多谢多谢
一个前端项目node_nodules 500M+源码 简直恐怖如斯
antd 项目更夸张,记得是 700M+
在 pnpm 管理模块时,使用软链解决了同一项目内模块复用的问题,使用硬链解决了跨项目复用的问题。为什么不统一使用硬链?是为了减少对源文件的直接引用吗?在删除硬链时直接让软链失效?
在 pnpm 管理模块时,使用软链解决了同一项目内模块复用的问题,使用硬链解决了跨项目复用的问题。为什么不统一使用硬链?是为了减少对源文件的直接引用吗?在删除硬链时直接让软链失效?
想了一下,硬链可以链接文件,不能处理文件夹;软链可以处理文件夹。pnpm在第二层使用软链的可能2个原因:一是维护模块层级目录结构,这里就只能使用软链处理目录;二是硬链只链接的具体文件,同一项目内的各模块软链链接的是目录
所以不能放弃本地这个概念 直接从网络上使用吗
网络速度不可控,而且在本地场景下,各个 npm 工具都会有全局缓存,所以磁盘空间相对还好,毕竟磁盘不值钱。
我们在做 cnpm rapid 的 fuse 方案的时候,有考虑过要不要 fuse 直接映射远程 tgz 的,实践效果一般。
另外,硬链接有一个坑就是,如果你在 A 项目下修改了某个文件进行调试,忘记改回去,在 B 项目就会被误引入。
npm 也就速度慢点、磁盘占用多点。但遇到无法解决的依赖故障,直接删除 node_modules 目录然后重新安装依赖就可以解决。
pnpm 的全局依赖你敢轻易动?
但修改 node_module 来调试,其实是一个非常常见的行为,你也无法要求 Node 开发者都知道 pnpm 是全局共享依赖的。
所以这个坑,必然会一直在。