pnpm 的全局 store 是什么?如何管理和清理?
pnpm 之所以能在磁盘占用和安装速度上远超 npm 和 yarn,核心就在于其全局 store 机制。理解 store 的原理,不仅能帮你排查依赖问题,还能在日常开发中做出更好的决策。
全局 store 是什么
全局 store 是 pnpm 在本地维护的一个集中式依赖仓库。所有项目安装的包,其文件都只存放在 store 中一份,项目通过硬链接(hard link)引用这些文件,而非复制副本。
这意味着:10 个项目都用 lodash@4.17.21,磁盘上只占一份 lodash 的空间。
Store 的位置与结构
默认情况下,store 位于用户主目录下:
bash# macOS / Linux ~/.local/share/pnpm/store # Windows %LOCALAPPDATA%/pnpm/store # 查看实际路径 pnpm store path
你可以通过 .npmrc 自定义 store 位置:
shellstore-dir = /path/to/custom/store
store 内部采用内容寻址存储(Content-Addressable Storage,简称 CAFS)结构:
shell~/.local/share/pnpm/store/ ├── v3/ # store 版本号 │ └── files/ # 基于内容 hash 组织的文件 │ ├── 00/ │ │ ├── abc123... # 文件内容,以 sha256 hash 命名 │ │ └── def456... │ └── ... └── metadata.json
每个文件按其内容的 SHA-256 哈希值存储。内容相同的文件只存一份,无论它属于哪个包的哪个版本。这就是 pnpm 节省磁盘空间的根本原因。
内容寻址存储(CAFS)与三层架构
pnpm 的依赖管理采用三层架构:
- 全局 store(CAFS):实际文件存放处,按内容哈希索引
- 虚拟存储(Virtual Store):每个项目的
node_modules/.pnpm/目录,存放硬链接 - 依赖解析层:
node_modules中的符号链接,形成最终的可访问结构
当执行 pnpm install 时,pnpm 先检查 store 中是否已有对应文件的哈希值。如果有,直接创建硬链接到项目的虚拟存储;如果没有,先下载到 store 再创建链接。
硬链接与 inode 的关系
硬链接是理解 pnpm store 的关键。在文件系统中,每个文件都有一个 inode(索引节点),硬链接使得多个文件路径指向同一个 inode:
shell全局 store: ~/.local/share/pnpm/store/v3/files/00/abc123 (inode: 98765) ↓ 硬链接 项目A: project-a/node_modules/.pnpm/lodash@4.17.21/lodash.js → inode 98765 项目B: project-b/node_modules/.pnpm/lodash@4.17.21/lodash.js → inode 98765
关键特性:
- 硬链接不占额外磁盘空间,因为它们指向同一块数据
- 修改任一链接的文件内容,所有链接都会同步变化(所以不要手动修改 node_modules 里的文件)
- 删除一个链接不影响其他链接,只要还有链接存在,数据就不会丢失
Store 管理:常用命令
bash# 查看 store 路径 pnpm store path # 查看 store 状态(检查是否有损坏的包) pnpm store status # 清理未被任何项目引用的包 pnpm store prune # pnpm 9+ 可验证 store 完整性 pnpm store verify
其中 pnpm store prune 是最常用的管理命令。它会扫描 store 中所有包,检查是否还有项目通过硬链接引用它们,未被引用的包将被删除释放空间。
什么时候需要清理 store
以下场景建议执行 pnpm store prune:
- 升级 pnpm 大版本后:新版本的 store 结构可能不同,旧版本缓存可清理
- 大量项目删除后:这些项目曾安装的包可能不再被任何项目引用
- 磁盘空间紧张时:prune 通常能释放可观的磁盘空间
- 依赖版本迭代后:项目升级了依赖版本,旧版本包可能不再被引用
注意:pnpm store prune 是安全操作,它只删除没有被任何项目引用的包,不会影响正在使用的依赖。
多 Store 配置
在特定场景下,你可能需要使用多个 store:
bash# 不同分区/文件系统的项目需要独立的 store # 因为硬链接不能跨文件系统 # project-a/.npmrc store-dir = /data/store-a # project-b/.npmrc store-dir = /data/store-b
跨文件系统是使用多 store 最常见的原因。如果项目和 store 在不同磁盘分区,硬链接会失败,pnpm 会退化为复制文件,失去空间优势。
pnpm 11 的 store 变更
pnpm 11 对 store 做了重要改进:
- SQLite 索引:用 SQLite 数据库替代了原来每个包的 JSON 索引文件,减少了系统调用,安装速度进一步提升
- 项目追踪:通过
{storeDir}/v11/projects/中的符号链接注册项目,pnpm 能准确追踪哪些项目在使用哪些包,让store prune更加精准 - 全局虚拟存储:全局安装的包现在有独立的隔离环境,每个
pnpm add -g的包都有自己的目录和 lockfile
如果你在 pnpm 11 中遇到 store 相关问题,先确认 store 版本已正确迁移。
常见问题排查
安装时报硬链接错误:检查项目与 store 是否在同一文件系统。如果不是,配置 store-dir 到同一分区。
store prune 后磁盘空间没变化:可能有其他项目仍在引用这些包。用 pnpm store status 确认哪些包仍在使用。
误删了 .pnpm-store 目录:不会损坏已有项目,但下次安装依赖时需要重新下载。执行 pnpm install 即可重建。