3.7 KiB
3.7 KiB
name, description
| name | description |
|---|---|
| pnpm-store | pnpm 的内容可寻址存储系统,使其安装速度快且磁盘占用低 |
pnpm 存储
pnpm 使用内容可寻址存储来节省磁盘空间并加速安装。所有包仅全局存储一次,并通过硬链接映射到项目的 node_modules。
工作原理
- 全局存储:包只下载一次,存入中央存储
- 硬链接:项目通过链接引用存储,而非复制文件
- 内容可寻址:文件按内容哈希存储,相同文件自动去重
存储布局
~/.pnpm-store/ # 全局存储(默认位置)
└── v3/
└── files/
└── <hash>/ # 按内容哈希存储的文件
project/
└── node_modules/
├── .pnpm/ # 虚拟存储(到全局存储的硬链接)
│ ├── lodash@4.17.21/
│ │ └── node_modules/
│ │ └── lodash/
│ └── express@4.18.2/
│ └── node_modules/
│ ├── express/
│ └── <deps>/ # 依赖的扁平结构
├── lodash -> .pnpm/lodash@4.17.21/node_modules/lodash
└── express -> .pnpm/express@4.18.2/node_modules/express
存储命令
# 显示存储位置
pnpm store path
# 移除未被引用的包
pnpm store prune
# 检查存储完整性
pnpm store status
# 将包添加到存储而不安装
pnpm store add <pkg>
配置
存储位置
# .npmrc
store-dir=~/.pnpm-store
# 或使用环境变量
PNPM_HOME=~/.local/share/pnpm
虚拟存储
虚拟存储(node_modules 中的 .pnpm 目录)包含指向全局存储的符号链接:
# 自定义虚拟存储位置
virtual-store-dir=node_modules/.pnpm
# 替代的扁平布局
node-linker=hoisted
磁盘空间优势
pnpm 可显著节省磁盘空间:
- 去重:同一包版本在所有项目中只存储一次
- 内容去重:不同包中的相同文件只存储一次
- 硬链接:无需复制,仅需链接
检查磁盘占用
# 比较实际大小与表观大小
du -sh node_modules # 表观大小
du -sh --apparent-size node_modules # 包含硬链接计数
Node Linker 模式
配置 node_modules 的结构:
# 默认:符号链接结构(推荐)
node-linker=isolated
# 扁平的 node_modules(类似 npm,用于兼容)
node-linker=hoisted
# PnP 模式(实验性,类似 Yarn PnP)
node-linker=pnp
隔离模式(默认)
- 严格的依赖解析
- 无幻影依赖
- 包只能访问已声明的依赖
提升模式
- 类似 npm 的扁平
node_modules - 用于兼容不支持符号链接的工具
- 失去严格性优势
副作用缓存
缓存原生模块的构建输出:
# 启用副作用缓存
side-effects-cache=true
# 将副作用存储在项目中(而非全局存储)
side-effects-cache-readonly=true
跨机器共享存储
在 CI/CD 中可以共享存储:
# GitHub Actions 示例
- uses: pnpm/action-setup@v4
with:
run_install: false
- name: 获取 pnpm 存储目录
shell: bash
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
故障排除
存储损坏
# 验证并修复存储
pnpm store status
pnpm store prune
硬链接问题(网络驱动器、Docker)
# 使用复制而非硬链接
package-import-method=copy
权限问题
# 修复存储权限
chmod -R u+w ~/.pnpm-store