作为一个开发者,你可能已经习惯了使用 pnpm 来替代 npm 或 yarn,因为它极快且节省磁盘空间。但你是否好奇过:那些原本塞满磁盘的 node_modules 文件,在 pnpm 中到底去了哪里?
今天我们就来深入扒一扒 pnpm 的文件存储架构,带你彻底搞懂从项目本地到全局环境的文件流向。
一、 项目本地:当你运行 pnpm install 时
在传统的 npm/yarn 中,依赖包是被完整复制到项目的 node_modules 中的。但在 pnpm 中,文件存储采用了 “三层架构”,利用了**硬链接(Hard Links)和符号链接(Symlinks)**的魔法。
1. 表层:node_modules(符号链接)
这是你肉眼直接看到的目录。
- 内容:你只会在根目录下看到你在
package.json中声明的直接依赖。 - 机制:这些其实不是真实的文件,而是符号链接(软链接)。
- 目的:解决“幽灵依赖”问题。你没声明的包,这里就没有,代码里就引用不到,非常安全。
2. 中层:node_modules/.pnpm(虚拟存储库)
这是 pnpm 的核心设计,被称为 Virtual Store。
- 内容:所有的依赖(包括直接依赖和它们所有的子依赖)都平铺在这里。
- 格式:通常以
包名@版本号的格式命名文件夹。 - 机制:这里的每个文件,通过硬链接指向磁盘上真正的物理仓库。
- 目的:扁平化结构解决了依赖嵌套过深的问题,同时让 node 的解析算法能找到对应的包。
3. 底层:全局物理存储(Content-addressable Store)
这是文件真正占用磁盘空间的地方(同一磁盘分区下,所有项目共用一份)。
- 机制:基于内容寻址。只要文件内容没变,无论你在多少个项目中安装了
vue@3.0,硬盘上永远只有这一份文件。
二、 全局环境:当你运行 pnpm add -g 时
当你安装全局工具(如 nodemon, create-react-app)时,它们并不会乱跑,而是会被井井有条地安置在两个关键位置:
1. 可执行文件目录(Global Binaries)
这是存放命令的地方,也就是你的终端能敲出命令的原因。
- 作用:存放 cmd/sh 脚本或软链接,指向具体的库文件。
- 查看命令:
pnpm config get global-bin-dir - 常见位置:
- Windows:
%LOCALAPPDATA%\pnpm - macOS/Linux:
~/.local/share/pnpm
- Windows:
2. 全局库文件目录(Global Packages)
进入~/.local/share/pnpm/global/5/目录下, 下面也是包含.pnmp与node_modules, 逻辑与上面是一样的, 只不过是放在一个规定的全局路径下.
- 作用:存放包的代码逻辑。
- 查看命令:
pnpm root -g - 常见位置:通常在
global-bin-dir下的global/5/node_modules目录中。
三、 终极答案:物理文件到底在哪?
无论是项目里的依赖,还是全局安装的工具,它们物理上的真身都汇聚在同一个地方,我们称之为 Global Store(全局存储)。
如何找到它?
在终端运行:
pnpm store path
常见路径:
- macOS/Linux:
~/.local/share/pnpm/store - Windows:
C:\Users\你的用户名\AppData\Local\pnpm\store
这里的机制是怎样的?
- pnpm 的省空间魔法:当你安装一个包时,pnpm 会先去这个 Global Store 看有没有。
- 有:直接在你的项目中创建一个硬链接指向这里(速度极快,几乎不占额外空间)。
- 没有:下载文件到这里,然后再创建硬链接。
四、 总结与命令速查表
pnpm 的设计哲学可以总结为:物理文件存一份(Global Store),各处引用靠链接(Symlink/Hardlink)。
为了方便记忆,这里有一份常用的路径查询命令清单:
| 你想找什么? | 运行这个命令 |
|---|---|
我的全局命令安装在哪了? (如 vite 放在哪) | pnpm config get global-bin-dir |
| 全局包的源码目录在哪? | pnpm root -g |
| 硬盘上真正的物理文件库在哪? | pnpm store path |
| 查看当前项目安装了哪些包? | pnpm list |
| 查看全局安装了哪些包? | pnpm list -g |
希望这篇文章能帮你彻底理清 pnpm 的文件结构!如果你觉得有用,不妨分享给团队里的小伙伴。