News

2026年包管理器之战:pnpm、npm与Yarn,你的最佳选择?

2026年包管理器之战:pnpm、npm与Yarn,你的最佳选择?

对于大多数开发者来说,包管理器通常是项目初期设置一次便可“束之高阁”的工具——直到某个环节出错,或者团队成员使用了不同的管理器,导致你的node_modules目录一团糟。

展望2026年,主流的三个包管理器依旧是npm、Yarn和pnpm。我的建议是:几乎所有新项目都应该优先选择pnpm。以下是具体原因。

快速对比

特性npmYarn (v1/Berry)pnpm
速度基线约快2倍约快3倍
磁盘占用高(复制)高/PnP极低(硬链接)
Monorepo支持Workspaces (基础)Workspaces (成熟)Workspaces (最佳)
锁文件package-lock.jsonyarn.lockpnpm-lock.yaml
幽灵依赖是(问题)是/否(PnP)否(严格)
Node内置

速度:pnpm 独占鳌头

pnpm采用内容寻址存储(content-addressable store)机制——包在磁盘上只存储一次,并通过硬链接(hard links)引用到各个项目中。

以下是安装速度对比:

  • 安装全新 React + TypeScript 项目
    • npm install: ~18秒
    • yarn install: ~9秒
    • pnpm install: ~5秒
  • 第二次安装(缓存预热)
    • npm install: ~9秒
    • yarn install: ~4秒
    • pnpm install: ~1.5秒

对于每天运行数十次构建的CI/CD流水线而言,这些时间累积起来的节省是非常可观的。

幽灵依赖:pnpm 的杀手级特性

使用npm和Yarn时,你的代码可能会意外地导入package.json中未声明的包——这些包作为传递性依赖(transitive dependencies)被提升(hoisted)到node_modules目录中。

例如:

// 这在npm中可能运行,但在pnpm中会正确地报错:
import { something } from 'a-transitive-dep-you-never-declared'

pnpm使用符号链接(symlinked)的node_modules结构,这意味着你只能导入那些你明确声明在package.json中的包。这能捕获npm/Yarn默默允许的真实bug。

Monorepos:pnpm 再次胜出

pnpm在Monorepo支持方面表现卓越。

一个典型的pnpm-workspace.yaml配置示例:

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

pnpm提供了一系列强大的Monorepo命令:

pnpm --filter @myapp/ui build         # 构建特定工作区
pnpm --filter @myapp/api add express  # 为特定工作区添加依赖
pnpm -r test                          # 并行运行所有工作区的测试

Turborepo、Nx以及大多数Monorepo工具都与pnpm完美兼容。

何时继续使用 npm

在以下情况下,npm仍然是合理的选择:

  • 编写公共 npm 包: 开发者对此最为熟悉,降低贡献门槛。
  • 需要零配置的快速脚本: 对于简单脚本,npm的即用性更强。
  • 团队成员非主攻 JavaScript: 对于只需“能用就行”的非专业JavaScript开发者团队。

尽管npm v9/10相比旧版本已有显著改进,但它在速度上仍是三者中最慢的。

何时使用 Yarn

  • Yarn 1 (Classic): 已进入维护模式。不建议用于新项目。
  • Yarn Berry (v2+): 其Plug'n'Play (PnP) 功能彻底消除了node_modules目录——但工具链的兼容性仍有待提高。仅当你完全致力于实现零安装(zero-install)工作流时,才值得考虑。

从 npm/Yarn 迁移到 pnpm

要开始使用 pnpm,首先全局安装它:

npm install -g pnpm

安装完成后,你就可以在项目中运行pnpm install来管理依赖了。

↗ 阅读原文