发展中出现的问题
npm2 及以前版本,packjson的结构和nodemodule的结构完全相同,也就是说依赖是嵌套再nodemodules中的
但是会有以下缺陷:
- 如果依赖的依赖有重复的依赖,则会重复安装依赖,node_modules的占用空间会变大
yarn 和 npm3 的出现解决了上面的问题,他们通过将依赖打平,此时node_modules的目录是扁平化的
这个方案解决了重复安装依赖的问题,但是带来了新的问题
- 一个依赖的子依赖也会被提升到node_modules顶层,所以他能被node resolve,因此这个依赖可以被引用,即使他没有再packagejson中定义,这就叫做幽灵依赖
- 当幽灵依赖被删除,直接引用幽灵依赖的内容也会出错
包管理工具依赖模块解析的能力,(ESM 和 CommonJs)。而打包的时候依赖webpack等工具的包解析能力。一般流程是:在当前依赖层级下搜素依赖,如果没有,向上一层搜索,直到全局,没有则报错。类似于JS的上下文。
Pnpm 解决方案
Pnpm 的node_modules 结构沿用了 npm2 的结构,package.json 和 node_module 同构,这样避免了幽灵依赖
对于重复的子依赖,Pnpm 利用链接解决了这个问题。
- 硬链接:inode 指针直接指向文件
- 符号链接:指针指向一个新的inode,这个inode再指向目标文件
相同的子依赖通过符号链接复用已有的依赖,其实最终都再store中获取对应版本
记录Diff
值得一提的是,store对于同一依赖的不同版本不是全部保存,而是保存一个版本并记录对应版本的diff
所以对于一个依赖包,pnpm store中其实只有一个完整的包源文件,重复依赖的空间占用很小
笔者才疏学浅,望各位读者多多担待不吝赐教。部分插图来自网络,侵删。