Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

精读《pnpm》 #435

Closed
ascoders opened this issue Aug 14, 2022 · 17 comments
Closed

精读《pnpm》 #435

ascoders opened this issue Aug 14, 2022 · 17 comments

Comments

@ascoders
Copy link
Owner

ascoders commented Aug 14, 2022

pnpm 创造了目前最高效、最合理的 node_modules 管理方式,值得使用,也更值得我们学习。


精读《pnpm》

@mater1996
Copy link

mater1996 commented Aug 18, 2022

@ry928330
Copy link

为什么源文件删除之后,对于硬连接的形式没有影响而只对软连接的形式有影响呢,按照您的文章的理解的话,源文件删除了,那么硬连接指针指向的源文件地址就没有源文件了,那就找不到东西了。

@waitingsong
Copy link

waitingsong commented Aug 19, 2022

为什么源文件删除之后,对于硬连接的形式没有影响而只对软连接的形式有影响呢,按照您的文章的理解的话,源文件删除了,那么硬连接指针指向的源文件地址就没有源文件了,那就找不到东西了。

硬链接和”源文件“是相同的指向结构,可以认为硬链接就是源文件的(副本)。删除其中任意一个时,操作系统检查该数据还有一个链接引用,于是就不会删除源数据,而只是删除链接 inode。
这就好比 js 里面的变量引用,你可以把一个变量赋值给很多变量,gc 的时候如果检查数据还有引用,那么就不会清楚数据源。

@Zephylaci
Copy link

我其实有点好奇,pnpm的内容寻址是怎么实现的,.pnpm-store 下存储的是,以文件内容hash后得到的地址,怎么diff虽然我也很好奇,但我更疑惑怎么关联或者说读取呢?
比如我在项目A装了 baz@1.0.0 这时store下有了对应的hash标识的文件
这时我在项目B也想装 baz@1.0.0,但我在下载前并不知道 文件对应的 内容,那应该也不知道文件对应的hash吧?如果每次都是重新下载感觉似乎不太友好?

@ry928330
Copy link

哦哦,那其实“源文件”也并非磁盘存储处,也只是一个指针的意思吧

@ascoders
Copy link
Owner Author

@Tarhyru 相同包名相同版本号不会重复下载。.pnpm-store 存储的 diff 算法场景是:版本号不同时需下载,但仅存储 diff 文件内容。

@waitingsong
Copy link

waitingsong commented Aug 21, 2022

哦哦,那其实“源文件”也并非磁盘存储处,也只是一个指针的意思吧

是的。

  • 源文件 (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)会失败。

@a243065157
Copy link

a243065157 commented Aug 21, 2022 via email

@zhangenming
Copy link

所以不能放弃本地这个概念 直接从网络上使用吗

@zhangenming
Copy link

一个前端项目node_nodules 500M+源码 简直恐怖如斯

@ry928330
Copy link

哦哦,那其实“源文件”也并非磁盘存储处,也只是一个指针的意思吧

是的。

  • 源文件 (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 多谢多谢

@waitingsong
Copy link

一个前端项目node_nodules 500M+源码 简直恐怖如斯

antd 项目更夸张,记得是 700M+

@heyunjiang
Copy link

在 pnpm 管理模块时,使用软链解决了同一项目内模块复用的问题,使用硬链解决了跨项目复用的问题。为什么不统一使用硬链?是为了减少对源文件的直接引用吗?在删除硬链时直接让软链失效?

@heyunjiang
Copy link

在 pnpm 管理模块时,使用软链解决了同一项目内模块复用的问题,使用硬链解决了跨项目复用的问题。为什么不统一使用硬链?是为了减少对源文件的直接引用吗?在删除硬链时直接让软链失效?

想了一下,硬链可以链接文件,不能处理文件夹;软链可以处理文件夹。pnpm在第二层使用软链的可能2个原因:一是维护模块层级目录结构,这里就只能使用软链处理目录;二是硬链只链接的具体文件,同一项目内的各模块软链链接的是目录

@atian25
Copy link

atian25 commented Sep 20, 2022

所以不能放弃本地这个概念 直接从网络上使用吗

网络速度不可控,而且在本地场景下,各个 npm 工具都会有全局缓存,所以磁盘空间相对还好,毕竟磁盘不值钱。
我们在做 cnpm rapid 的 fuse 方案的时候,有考虑过要不要 fuse 直接映射远程 tgz 的,实践效果一般。

另外,硬链接有一个坑就是,如果你在 A 项目下修改了某个文件进行调试,忘记改回去,在 B 项目就会被误引入。

@waitingsong
Copy link

waitingsong commented Sep 20, 2022

npm 也就速度慢点、磁盘占用多点。但遇到无法解决的依赖故障,直接删除 node_modules 目录然后重新安装依赖就可以解决。
pnpm 的全局依赖你敢轻易动?

@atian25
Copy link

atian25 commented Sep 20, 2022

但修改 node_module 来调试,其实是一个非常常见的行为,你也无法要求 Node 开发者都知道 pnpm 是全局共享依赖的。
所以这个坑,必然会一直在。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants