跳到主要内容

npm、Yarn、pnpm 到底有什么区别?一篇讲明白

7 分钟阅读

如果你刚接触前端工程化,第一次看到 npm installyarn installpnpm install,大概率会有一个疑问:

它们不都是“装包”的吗?为什么会有三个?

答案是:它们做的是同一件事,但解决问题的方式不一样。

  • npm 是 Node.js 官方自带的包管理器,历史最久,生态最稳。
  • Yarn 是在 npm 早期体验不够好的时候出现的,重点解决“慢”和“不稳定”。
  • pnpm 是在 Yarn 和 npm 继续发展之后,进一步解决“磁盘浪费”和“依赖不严谨”的问题。

这篇文章不讲太多绕人的术语,只用一条主线讲清楚:

为什么会从 npm 发展到 Yarn,再发展到 pnpm?


一、先说结论:新手该怎么理解这三个工具?

你可以先把它们理解成三个版本的“快递仓库管理系统”:

  • npm:最早上线,先把“包能装下来”这件事解决了。
  • Yarn:发现 npm 早期装得慢、装得不稳,于是把流程优化了。
  • pnpm:继续往前走,开始追求“更省空间、更快、更严格”。

所以它们并不是谁“取代”谁,而是在不同阶段针对不同痛点做优化

如果只想先记一句话:

  • 小项目、通用项目:npm 完全够用。
  • 注重安装速度、磁盘空间、Monorepo:更推荐 pnpm
  • Yarn 依然有人用,但新项目里相较前两者已经没那么常见。

二、它们到底是干什么的?

三者本质上都是 JavaScript / Node.js 的包管理器,主要做这几件事:

  • 安装依赖
  • 删除依赖
  • 更新依赖
  • 锁定依赖版本
  • 管理 node_modules

比如你写 React 项目时要安装 reactviteaxios,这些工具都会帮你从包仓库下载代码,并放到项目里可用的位置。

最常见的命令长这样:

npm install
yarn install
pnpm install

表面看它们差不多,但内部怎么存、怎么装、怎么复用依赖,差别很大。这也是为什么它们的速度、磁盘占用、依赖管理体验会不一样。


三、为什么会先有 npm,再有 Yarn 和 pnpm?

理解这件事最好的方法,不是背定义,而是看它们分别解决了什么问题。

1. npm 先解决“从无到有”

2010 年,npm 随 Node.js 一起出现。那个阶段最重要的不是“快不快”,而是:

JavaScript 终于有了一个像样的包管理系统。

开发者可以很方便地发布包、安装包、复用社区代码。这个意义非常大,Node.js 生态能爆发,npm 功不可没。

但随着项目越来越大,问题也开始暴露。

2. Yarn 解决“太慢、太不稳”

后来大家发现,早期 npm 在大型项目里有几个明显问题:

  • 安装速度慢
  • 依赖容易重复安装
  • 不同机器安装结果不一定完全一致

于是 2016 年,Facebook 推出了 Yarn。它的重点很明确:

先把安装体验做得更快、更稳。

3. pnpm 解决“太占空间、依赖不够严格”

再往后,大家又发现一个问题:

你电脑里多个项目,往往装了大量重复依赖,但这些文件其实一模一样。

而且 npm / Yarn 早期常见的扁平化依赖结构,还会带来“幽灵依赖”问题。

于是 2017 年,pnpm 出现了。它的核心思路是:

同样的包,全局只存一份;项目里通过链接去复用。

这让它在磁盘占用、安装速度、Monorepo 场景上都非常亮眼。


四、npm 做了什么?它为什么会遇到问题?

1. npm 最早的价值:把包管理标准化

在 npm 出现之前,前端和 Node.js 世界的依赖管理非常零散。npm 出现后,开发者终于可以:

  • 用统一命令安装依赖
  • 通过 package.json 管理项目依赖
  • 从公共仓库下载别人发布的包

这个阶段的 npm,最大的贡献是:

让整个 Node.js 生态跑起来。

2. 早期 npm 的问题:依赖越多,项目越重

早期 npm 会采用更偏“嵌套”的依赖结构。简单理解就是:

每个包都可能在自己的目录里再放一份依赖。

结果就是,同一个依赖如果有多个版本,甚至相同版本,也可能在不同位置被重复安装。

像这样:

node_modules/
├── package-a/
│ └── node_modules/
│ └── package-b@1.0.0
└── package-d/
└── node_modules/
└── package-b@2.0.0

这会带来几个问题:

  • node_modules 很大
  • 安装时间越来越长
  • 依赖关系越来越复杂

3. npm 后来做了哪些改进?

后来 npm 也持续升级,比如:

  • 使用更扁平的依赖结构,减少重复安装
  • 引入 package-lock.json,让依赖版本更可控
  • 持续优化安装性能
  • 支持 workspaces

所以今天的 npm,已经不是“很早以前那个慢吞吞的 npm”了。

它现在依然是最通用、最稳妥、门槛最低的选择。


五、Yarn 为什么会火?它到底改进了什么?

1. Yarn 出现的背景很现实

当项目依赖变多之后,团队最怕的不是“不会装”,而是:

  • 装得太慢
  • 同事之间装出来结果不一样
  • CI 安装耗时太久

Yarn 就是冲着这些问题来的。

2. Yarn 的几个关键改进

并行安装

早期 npm 的安装过程更偏串行,Yarn 把很多步骤并行化了,所以体感速度明显更快。

更好的缓存

Yarn 会把下载过的包缓存起来,再次安装时可以更快复用。

这对下面这些场景很有帮助:

  • 频繁删除再安装依赖
  • 切分支后重新安装
  • CI 重复构建

yarn.lock

锁文件的意义很简单:

把“这次安装出来的精确版本”记录下来。

这样团队里每个人、包括 CI,安装结果就更一致,不容易出现:

“为什么你能跑,我这边不行?”

3. Yarn 的局限

Yarn 虽然让安装体验更好了,但它并没有彻底解决两个问题:

  • node_modules 依然可能很大
  • 依赖管理仍然不够“严格”

也就是说,Yarn 主要解决的是速度和一致性,不是空间复用和依赖隔离。


六、pnpm 为什么越来越受欢迎?

如果说 npm 和 Yarn 的主要思路是“把依赖装到项目里”,那么 pnpm 更像是在说:

没必要每个项目都存一整份一样的东西。

1. pnpm 最核心的优势:省空间

假设你电脑上有 3 个前端项目,它们都用了 reacttypescripteslint

用传统方式时,三个项目的 node_modules 里可能各有一份,浪费很明显。

pnpm 的做法是:

  • 全局维护一个统一的依赖存储区
  • 相同版本的包只保存一份
  • 各项目通过链接方式使用这些包

所以 pnpm 的磁盘占用通常更小。

2. pnpm 为什么通常也更快?

因为它有两层优势:

  • 能并行安装
  • 已有包可以直接复用,不用每个项目都重新“存一遍”

尤其当你电脑里项目很多时,这种优势会越来越明显。

3. pnpm 的另一个关键点:依赖更严格

这是很多人第一次接触 pnpm 时最容易踩坑、但也是它最有价值的地方。

先看一个例子。

你的 package.json 里只写了:

{
"dependencies": {
"package-a": "^1.0.0"
}
}

package-a 自己依赖了 package-b

在某些旧的依赖结构下,你可能会“误打误撞”直接这样写:

import { something } from 'package-b'

虽然你根本没有在自己的 package.json 里声明 package-b,代码却可能还能跑。

这就叫幽灵依赖

问题在于:

它能跑,不代表它对。

一旦换环境、换工具、换版本,就可能突然出问题。

pnpm 更强调“你声明了什么,就只能用什么”,所以它更容易帮你提前发现依赖管理不规范的问题。

这也是为什么很多团队会觉得:

pnpm 一开始更严格,但长期更省心。


七、几个容易混淆的概念,顺手讲明白

1. 锁文件是什么?

锁文件就是把依赖安装结果“钉死”。

常见对应关系:

  • npm 对应 package-lock.json
  • Yarn 对应 yarn.lock
  • pnpm 对应 pnpm-lock.yaml

它的价值主要有两个:

  • 团队成员安装结果更一致
  • CI / 线上环境更稳定

2. 什么是“幽灵依赖”?

一句话解释:

你没声明,但你居然还能用到的依赖。

这不是“方便”,而是“隐患”。

3. pnpm 里的“硬链接 / 软链接”是什么?

如果你不是很关心底层细节,可以只记住这个结论:

  • 硬链接:多个地方看起来都有这个文件,但底层其实共享同一份内容
  • 软链接:像一个指向真实位置的快捷方式

pnpm 会利用这些机制,在兼容 Node.js 模块解析规则的同时,实现复用依赖、节省空间、严格隔离

你不需要天天研究这些名词,但知道它们是 pnpm 的技术基础就够了。


八、三者怎么选?这是最实用的部分

很多文章讲到最后,读者还是不知道项目里到底该用哪个。这里直接给建议。

1. 如果你想要最稳妥、最省心

npm

原因很简单:

  • Node.js 自带
  • 不需要额外安装
  • 生态兼容性最好
  • 大多数教程默认都能直接跑

适合:

  • 新手入门
  • 普通前端项目
  • 对团队统一要求不高的项目

2. 如果你更在意工程效率

pnpm

它特别适合:

  • 依赖很多的项目
  • 多项目并行开发
  • Monorepo
  • 希望依赖关系更严格的团队

如果你的项目已经进入“工程化”阶段,pnpm 往往是更现代的选择。

3. Yarn 什么时候会用到?

主要是两种情况:

  • 老项目历史上就在用 Yarn
  • 团队对 Yarn 的工具链已经很熟

如果是存量项目,通常没必要为了“追新”强行迁移。

但如果是新项目,今天大多数情况下会更倾向于在 npmpnpm 之间选。


九、一个简单对比表

工具最大特点优点可能的不足适合谁
npm官方默认上手简单、兼容性好、生态稳大型项目下不一定是最优体验大多数普通项目、新手
Yarn早期以速度和锁文件见长体验成熟、老项目常见新项目存在感相对下降已在用 Yarn 的团队
pnpm省空间、严格依赖、Monorepo 友好快、占用小、依赖更规范初次使用时可能会暴露历史依赖问题工程化项目、中大型项目

十、把这段历史真正记住,只要抓住一条线

你可以把它们的演进记成一句话:

npm 先解决“能不能管理包”,Yarn 解决“装得快不快、稳不稳”,pnpm 解决“占不占空间、依赖严不严”。

所以它们的关系不是谁“打败”谁,而是前端工程随着项目规模变大,不断提出新的要求:

  • 要更快
  • 要更稳
  • 要更省
  • 要更适合大型项目和 Monorepo

这也是前端工具链演进的一个缩影:

先能用,再好用,最后追求更高的工程效率。


十一、最后给一个不纠结版本的建议

如果你不想看太多历史,只想知道现在怎么选,可以直接参考:

  • 想省事,选 npm
  • 想更现代的工程体验,选 pnpm
  • 老项目已经在用 Yarn,通常继续用就行

对于大部分新项目来说,这已经足够了。

如果以后你再看到这些命令:

npm install
yarn install
pnpm install

你就知道,它们表面都叫“安装依赖”,但背后代表的是三代不同的工程优化思路。

Loading Comments...