【pnpm】什么是 pnpm:高效、快速且节省磁盘空间的 JavaScript 包管理器
pnpm 是一个高效、快速且节省磁盘空间的 JavaScript 包管理器,旨在解决传统包管理器(如 npm 和 Yarn Classic)在性能、磁盘空间使用和依赖管理结构上的不足。它通过创新的内容可寻址存储和非扁平化的 node_modules 结构,提供更高效的依赖安装和管理方式。pnpm 不仅适用于前端和后端项目,还在 Node.js 生态系统中表现出色,广泛用于现代 JavaScript 项目。
以下是对 pnpm 的详细介绍,涵盖其初衷、核心功能、安装方式、与其他包管理器的比较以及使用场景。
一、pnpm 的项目初衷
pnpm 的设计目标是解决传统包管理器(如 npm 和 Yarn Classic)在磁盘空间、安装速度和依赖管理结构上的问题。其核心优势体现在以下三个方面:
1. 节省磁盘空间
pnpm 使用**内容可寻址存储(Content-Addressable Storage, CAS)**来管理依赖项,与 npm 和 Yarn Classic 相比显著减少磁盘空间占用。其工作原理如下:
- 单一存储位置:所有依赖文件存储在硬盘上的统一位置(通常是
~/.pnpm-store),不同项目共享同一版本的依赖。 - 硬链接机制:在项目中安装依赖时,pnpm 使用硬链接将存储中的文件链接到项目的
node_modules目录,而不复制文件,从而避免占用额外磁盘空间。 - 增量更新:当依赖更新时,仅存储发生变化的文件。例如,一个包有 100 个文件,新版本只修改了 1 个文件,pnpm 只会添加这 1 个文件,而不是重新存储整个包。
这使得 pnpm 在多项目开发中能够显著节省磁盘空间,尤其是在依赖数量多或项目规模大的场景下。
2. 提高安装速度
pnpm 的安装过程分为三个阶段,与传统包管理器的流程相比更高效:
- 依赖解析:识别项目所需的依赖,检查内容可寻址存储中是否已存在,若不存在则下载。
- 目录结构计算:根据依赖关系计算出
node_modules目录的结构。 - 链接依赖:从存储区中获取已有的依赖文件,通过硬链接将其加入
node_modules目录。
相比 npm 和 Yarn Classic 的传统三阶段流程(解析、下载、写入),pnpm 的方法避免了重复下载和写入,从而显著提高了安装速度。
3. 创建非扁平的 node_modules 结构
传统包管理器(如 npm 和 Yarn Classic)会将所有依赖提升到 node_modules 的根目录,导致“扁平化”结构。这种结构可能引发以下问题:
- 项目可以直接访问非声明的依赖(依赖的依赖),可能导致意外的依赖冲突或安全问题。
- 依赖结构复杂,难以理解和管理。
pnpm 默认使用**符号链接(symlinks)**创建一个非扁平的 node_modules 结构:
- 项目的直接依赖通过符号链接放置在
node_modules根目录。 - 依赖的依赖(子依赖)存储在
node_modules/.pnpm目录中,并通过符号链接与直接依赖关联。 - 这种结构确保只有声明的依赖可以被项目直接访问,增强了隔离性和安全性,同时与 Node.js 的模块解析机制完全兼容。
如果工具不支持符号链接,pnpm 提供 nodeLinker=hoisted 配置,生成类似 npm 的扁平化结构以确保兼容性。
二、pnpm 的核心功能
pnpm 提供了丰富的功能,使其在现代 JavaScript 开发中具有竞争优势。以下是其主要功能的概述,基于功能比较文档:
1. 功能概览
| 功能 | pnpm | Yarn | npm | 备注 |
|---|---|---|---|---|
| Workspace 支持 | ✅ | ✅ | ✅ | 支持 monorepo 工作流。 |
| 隔离的 node_modules | ✅ | ✅ | ✅ | pnpm 默认使用隔离结构,增强依赖安全性。 |
| Hoisted node_modules | ✅ | ✅ | ✅ | npm 默认使用扁平化结构,pnpm 可通过配置支持。 |
| Plug’n’Play | ✅ | ✅ | ❌ | Yarn 默认使用,pnpm 可选支持。 |
| 自动安装 peer 依赖 | ✅ | ❌ | ✅ | pnpm 和 npm 支持自动安装 peerDependencies。 |
| 零安装 | ❌ | ✅ | ❌ | Yarn 支持零安装(Zero-Install),pnpm 暂不支持。 |
| 修补依赖 | ✅ | ✅ | ❌ | pnpm 和 Yarn 支持修改依赖代码。 |
| 管理 Node.js 版本 | ✅ | ❌ | ❌ | pnpm 通过 pnpm env 命令支持 Node.js 版本管理。 |
| 管理自身版本 | ✅ | ✅ | ❌ | pnpm 和 Yarn 支持版本自管理。 |
| 锁文件 | ✅ | ✅ | ✅ | pnpm 使用 pnpm-lock.yaml。 |
| 内容可寻址存储 | ✅ | ✅ | ❌ | Yarn 在特定配置下支持,pnpm 默认使用。 |
| 动态包执行 | ✅ | ✅ | ✅ | pnpm 使用 pnpm dlx,类似 npx 和 yarn dlx。 |
| 副作用缓存 | ✅ | ❌ | ❌ | pnpm 支持缓存构建副作用,提升重复构建性能。 |
| 目录支持(Catalogs) | ✅ | ❌ | ❌ | pnpm 独有功能,简化 monorepo 依赖管理。 |
| 配置依赖 | ✅ | ❌ | ❌ | pnpm 支持配置化依赖管理。 |
| JSR 注册表支持 | ✅ | ✅ | ❌ | pnpm 和 Yarn 支持 JSR 注册表。 |
| 脚本运行前自动安装 | ✅ | ❌ | ❌ | pnpm 在运行脚本前自动安装依赖,Yarn 的 PnP 可确保依赖最新。 |
| 钩子(Hooks) | ✅ | ✅ | ❌ | pnpm 和 Yarn 支持自定义钩子。 |
| 列出许可证 | ✅ | ✅ | ❌ | pnpm 通过 pnpm licenses list 支持,Yarn 需要插件。 |
2. 独特功能解析
- 内容可寻址存储:pnpm 的核心优势,通过单一存储和硬链接机制减少磁盘占用。
- 非扁平 node_modules:通过符号链接实现依赖隔离,防止意外访问子依赖。
- 副作用缓存:缓存构建过程中的副作用(如编译结果),提升重复构建效率。
- 目录(Catalogs):在 monorepo 项目中简化依赖版本管理,适合大型项目。
- Node.js 版本管理:通过
pnpm env命令管理 Node.js 版本,方便开发和 CI 环境配置。 - 自动安装 peer 依赖:简化依赖管理,减少手动配置的工作量。
三、pnpm 的安装方式
pnpm 提供了多种安装方式,适用于不同操作系统和使用场景。以下是详细的安装方法:
1. 前提条件
- 如果不使用独立脚本或
@pnpm/exe,需要安装 Node.js v18.12 或更高版本。 - 某些安装方式(如 Corepack)需要额外配置。
2. 使用独立脚本安装
无需预装 Node.js,可通过以下脚本安装 pnpm:
- Windows(PowerShell):
注意:Windows Defender 可能阻止可执行文件,建议使用 npm 或 Corepack。Invoke-WebRequest https://get.pnpm.io/install.ps1 -UseBasicParsing | Invoke-Expression - POSIX 系统(Linux/macOS):
或使用 wget:curl -fsSL https://get.pnpm.io/install.sh | sh -wget -qO- https://get.pnpm.io/install.sh | sh - - Docker 容器:
wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.bashrc" SHELL="$(which bash)" bash - - 安装特定版本:
curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=<version> sh -
3. 使用 Corepack 安装
Node.js v16.13+ 自带 Corepack,需先更新 Corepack:
npm install --global corepack@latest
启用 pnpm:
corepack enable pnpm
固定项目版本:
corepack use pnpm@latest-10
4. 使用其他包管理器
- npm:
或安装无需 Node.js 的版本:npm install -g pnpm@latest-10npm install -g @pnpm/exe@latest-10 - Homebrew(macOS/Linux):
brew install pnpm - winget(Windows):
winget install -e --id pnpm.pnpm - Scoop(Windows):
scoop install nodejs-lts pnpm - Chocolatey(Windows):
choco install pnpm - Volta:
volta install pnpm
5. 兼容性
pnpm 的版本与 Node.js 的兼容性如下:
| Node.js 版本 | pnpm 8 | pnpm 9 | pnpm 10 |
|---|---|---|---|
| Node.js 14 | ❌ | ❌ | ❌ |
| Node.js 16 | ✔️ | ❌ | ❌ |
| Node.js 18 | ✔️ | ✔️ | ✔️ |
| Node.js 20 | ✔️ | ✔️ | ✔️ |
| Node.js 22 | ✔️ | ✔️ | ✔️ |
6. 设置别名
为方便使用,可设置 pn 作为 pnpm 的别名:
- POSIX 系统:
在.bashrc、.zshrc或config.fish中添加:alias pn=pnpm - Windows(PowerShell):
添加:notepad $profile.AllUsersAllHostsset-alias -name pn -value pnpm
7. 更新与卸载
- 更新 pnpm:
pnpm self-update - 卸载 pnpm:
找到 pnpm 安装路径(使用which pnpm或where.exe pnpm.*),删除相关文件(如pnpm.cmd、pnpx.cmd),然后重新安装或完全移除。
四、pnpm 的优势与使用场景
1. 优势总结
- 节省磁盘空间:通过内容可寻址存储和硬链接机制,减少重复存储。
- 快速安装:分阶段安装流程,效率高于 npm 和 Yarn Classic。
- 依赖隔离:非扁平的
node_modules结构,防止意外访问子依赖。 - 功能丰富:支持 monorepo、Node.js 版本管理、副作用缓存等现代开发需求。
- 兼容性强:与 Node.js 生态系统无缝集成,支持多种安装方式和配置。
2. 使用场景
- 大型项目和 monorepo:pnpm 的目录(Catalogs)和 Workspace 支持使其非常适合管理复杂的大型项目。
- 磁盘空间受限环境:如 CI/CD 服务器或开发者的本地机器,pnpm 能显著减少存储需求。
- 高性能需求:快速安装和副作用缓存适合频繁构建的场景。
- 需要严格依赖隔离的项目:非扁平的
node_modules结构确保依赖安全性和可预测性。
五、与其他包管理器的比较
pnpm 在功能和性能上与 npm 和 Yarn Classic 相比有明显优势:
- npm:传统包管理器,扁平化
node_modules结构,磁盘占用高,安装速度较慢,缺少高级功能(如副作用缓存、Node.js 版本管理)。 - Yarn Classic:支持 Workspace 和 Plug’n’Play,但磁盘空间优化不如 pnpm,部分功能需要插件支持。
- pnpm:结合了 npm 的稳定性和 Yarn 的现代化功能,增加了内容可寻址存储、非扁平化结构等独特特性。
六、总结
pnpm 是一个现代化、高效的 JavaScript 包管理器,通过内容可寻址存储、非扁平的 node_modules 结构和快速安装流程,解决了传统包管理器在磁盘空间、安装速度和依赖管理上的痛点。其丰富的功能(如副作用缓存、Node.js 版本管理、Catalogs)使其成为 monorepo、大型项目和性能敏感场景的理想选择。无论是在本地开发还是 CI/CD 环境中,pnpm 都能提供卓越的性能和灵活性,是现代 JavaScript 开发者的优选工具。
七、参考资料
更多推荐


所有评论(0)