Back

pnpm 简介:比 npm 和 Yarn 更快的替代方案

pnpm 简介:比 npm 和 Yarn 更快的替代方案

如果你曾经看着 CI/CD 流水线花费数分钟安装依赖项,或者因为多个项目中的重复包而在开发机器上遇到磁盘空间不足的问题,那么你正在经历 pnpm 旨在解决的确切问题。这个高性能的包管理器提供了一种根本不同的依赖管理方法,可以将安装时间缩短 2-3 倍,并减少约 50% 的磁盘使用量。

核心要点

  • pnpm 使用内容寻址存储和硬链接来消除跨项目的重复包
  • 严格的依赖解析可防止幽灵依赖,并在生产环境之前捕获错误
  • 与 npm 相比,安装速度提高 2-3 倍,磁盘使用量减少 50%
  • 内置的工作区支持使其成为 monorepo 架构的理想选择

pnpm 的独特之处

与 npm 和 Yarn 在项目之间复制包不同,pnpm 使用内容寻址存储和硬链接来全局共享依赖项。当你在多个项目中安装 Express 时,npm 会在每个 node_modules 文件夹中创建单独的副本。pnpm 将其存储一次在 ~/.pnpm-store 中,并创建指向该单一副本的硬链接,从而大幅减少磁盘使用量,同时保持项目之间的完全隔离。

这种架构还可以防止”幽灵依赖”——这是一个常见问题,代码可能会意外导入未在 package.json 中列出的包。通过 pnpm 严格的 Node.js 模块解析,如果依赖项没有明确声明,你的代码就无法访问它,从而在错误到达生产环境之前捕获它们。

安装和设置

对于 Node.js 16.13 或更高版本,推荐的安装方法是使用 Corepack:

corepack enable
corepack prepare pnpm@latest --activate

或者,通过 npm 安装:

npm install -g pnpm

日常开发的基本命令

pnpm 的核心命令与 npm 的熟悉语法相似,同时添加了性能优化:

pnpm add express          # 添加生产依赖
pnpm add -D typescript    # 添加开发依赖
pnpm remove lodash       # 移除包
pnpm update             # 更新所有依赖
pnpm run build         # 执行 package.json 中的脚本

pnpm store 命令提供了管理全局包缓存的独特功能:

pnpm store status      # 检查存储健康状态
pnpm store prune      # 移除未引用的包

现代项目的配置

创建一个 .npmrc 文件来为你的团队配置 pnpm 行为:

strict-peer-dependencies=true
auto-install-peers=true
prefer-offline=true

这些设置强制执行对等依赖要求,自动安装对等依赖(Node.js 16+),并优先使用缓存的包以加快安装速度。

Monorepo 的工作区设置

对于 monorepo 项目,pnpm 的工作区支持在管理多个包方面表现出色。创建一个 pnpm-workspace.yaml 文件:

packages:
  - 'packages/*'
  - 'apps/*'

package.json 中使用 workspace: 协议链接工作区包:

{
  "dependencies": {
    "@myapp/shared": "workspace:*",
    "@myapp/ui": "workspace:^1.0.0"
  }
}

在所有工作区包中运行命令:

pnpm -r build                  # 构建所有包
pnpm --filter @myapp/api dev   # 在特定包中运行 dev 脚本

CI/CD 优化

对于 GitHub Actions,使用官方 pnpm action 配合 Node.js 22 LTS:

- uses: pnpm/action-setup@v4
  with:
    version: 9
- uses: actions/setup-node@v4
  with:
    node-version: 22
    cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm test

对于 GitLab CI,配置缓存以最大化 CI/CD 优化:

image: node:22

before_script:
  - corepack enable
  - corepack prepare pnpm@latest --activate

cache:
  key: pnpm-store-$CI_COMMIT_REF_SLUG
  paths:
    - .pnpm-store

install:
  script:
    - pnpm config set store-dir .pnpm-store
    - pnpm install --frozen-lockfile

--frozen-lockfile 标志通过在 pnpm-lock.yamlpackage.json 不匹配时失败来确保可重现的构建,防止开发和生产环境之间的偏差。

实践中的性能表现

从 npm 迁移的团队通常会看到安装速度提高 2-3 倍,这得益于 pnpm 高效的链接策略。一个拥有 500 个依赖项的中型项目,使用 npm 可能需要 60 秒,但使用 pnpm 只需要 20-25 秒。磁盘节省更加显著——在多个项目上工作的开发人员通常可以回收 5-10GB 的空间,因为重复的包被消除了。

结论

pnpm 通过创新架构而非渐进式改进,兑现了其更快、更高效的依赖管理承诺。其严格的依赖解析可以及早捕获错误,而工作区设置功能使其成为现代 monorepo 架构的理想选择。无论你是在优化 CI/CD 流水线还是管理复杂的全栈应用程序,pnpm 都能提供开发团队所需的性能和可靠性,同时不牺牲与现有 npm 生态系统的兼容性。

常见问题

pnpm 默认强制执行严格的对等依赖解析。除非你在配置中启用 auto-install-peers,否则它不会自动安装对等依赖。这可以防止版本冲突,并确保你的项目明确声明所有必需的依赖项。

可以,pnpm 与 npm 和 Yarn 项目完全兼容。只需在项目目录中运行 pnpm import,即可从现有的锁文件生成 pnpm-lock.yaml 文件。你的所有 npm 脚本和 package.json 配置无需修改即可工作。

即使从项目中卸载包后,包仍保留在全局存储中。这允许在以后需要时立即重新安装。定期运行 pnpm store prune 以移除未引用的包并释放磁盘空间。

当然可以。pnpm 已经可以用于生产环境,并被大型公司使用。在生产环境中使用 pnpm install --frozen-lockfile 以确保精确的依赖版本。确定性安装和严格的依赖解析实际上使部署比传统包管理器更可靠。

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay