npm vs pnpm

你的磁盘空间总是不够用?安装依赖总是慢如蜗牛?项目一多,node_modules 动辄几个 GB,每次 npm install 都要等上几分钟?如果你也遇到过这些痛点,那么这篇文章正是为你准备的。npm 作为 Node.js 官方默认工具,生态最全、兼容性最高;而 pnpm 则通过硬链接与符号链接实现了极速安装和极低磁盘占用。本文将从各自优势 、命令对比 、性能数据 、迁移指南 等方面全面解析,帮助你结合自身项目情况做出最合适的选型决策。你也可以参考 PNPM 官方文档 了解更详细的 pnpm vs npm 核心机制。 [1](https://pnpm.io/zh/pnpm-vs-npm), [2](https://juejin.cn/post/7505989436360261695), [3](https://www.runoob.com/nodejs/nodejs-npm.html), [4](https://zhuanlan.zhihu.com/p/1929579988274902650)
下面是 npm 与 pnpm 的核心对比图:
#mermaid-svg-D2cl7CwBlq3wZI9m{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-D2cl7CwBlq3wZI9m .error-icon{fill:#552222;}#mermaid-svg-D2cl7CwBlq3wZI9m .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-D2cl7CwBlq3wZI9m .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-D2cl7CwBlq3wZI9m .marker{fill:#333333;stroke:#333333;}#mermaid-svg-D2cl7CwBlq3wZI9m .marker.cross{stroke:#333333;}#mermaid-svg-D2cl7CwBlq3wZI9m svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-D2cl7CwBlq3wZI9m p{margin:0;}#mermaid-svg-D2cl7CwBlq3wZI9m .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-D2cl7CwBlq3wZI9m .cluster-label text{fill:#333;}#mermaid-svg-D2cl7CwBlq3wZI9m .cluster-label span{color:#333;}#mermaid-svg-D2cl7CwBlq3wZI9m .cluster-label span p{background-color:transparent;}#mermaid-svg-D2cl7CwBlq3wZI9m .label text,#mermaid-svg-D2cl7CwBlq3wZI9m span{fill:#333;color:#333;}#mermaid-svg-D2cl7CwBlq3wZI9m .node rect,#mermaid-svg-D2cl7CwBlq3wZI9m .node circle,#mermaid-svg-D2cl7CwBlq3wZI9m .node ellipse,#mermaid-svg-D2cl7CwBlq3wZI9m .node polygon,#mermaid-svg-D2cl7CwBlq3wZI9m .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-D2cl7CwBlq3wZI9m .rough-node .label text,#mermaid-svg-D2cl7CwBlq3wZI9m .node .label text,#mermaid-svg-D2cl7CwBlq3wZI9m .image-shape .label,#mermaid-svg-D2cl7CwBlq3wZI9m .icon-shape .label{text-anchor:middle;}#mermaid-svg-D2cl7CwBlq3wZI9m .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-D2cl7CwBlq3wZI9m .rough-node .label,#mermaid-svg-D2cl7CwBlq3wZI9m .node .label,#mermaid-svg-D2cl7CwBlq3wZI9m .image-shape .label,#mermaid-svg-D2cl7CwBlq3wZI9m .icon-shape .label{text-align:center;}#mermaid-svg-D2cl7CwBlq3wZI9m .node.clickable{cursor:pointer;}#mermaid-svg-D2cl7CwBlq3wZI9m .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-D2cl7CwBlq3wZI9m .arrowheadPath{fill:#333333;}#mermaid-svg-D2cl7CwBlq3wZI9m .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-D2cl7CwBlq3wZI9m .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-D2cl7CwBlq3wZI9m .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-D2cl7CwBlq3wZI9m .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-D2cl7CwBlq3wZI9m .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-D2cl7CwBlq3wZI9m .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-D2cl7CwBlq3wZI9m .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-D2cl7CwBlq3wZI9m .cluster text{fill:#333;}#mermaid-svg-D2cl7CwBlq3wZI9m .cluster span{color:#333;}#mermaid-svg-D2cl7CwBlq3wZI9m div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-D2cl7CwBlq3wZI9m .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-D2cl7CwBlq3wZI9m rect.text{fill:none;stroke-width:0;}#mermaid-svg-D2cl7CwBlq3wZI9m .icon-shape,#mermaid-svg-D2cl7CwBlq3wZI9m .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-D2cl7CwBlq3wZI9m .icon-shape p,#mermaid-svg-D2cl7CwBlq3wZI9m .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-D2cl7CwBlq3wZI9m .icon-shape .label rect,#mermaid-svg-D2cl7CwBlq3wZI9m .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-D2cl7CwBlq3wZI9m .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-D2cl7CwBlq3wZI9m .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-D2cl7CwBlq3wZI9m :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} pnpm
硬链接/软链接
全局单一存储
极速安装
杜绝幽灵依赖
原生 Monorepo
npm
生态最全
默认自带
扁平化 node_modules
磁盘占用高
安装速度较慢
对比维度
选择建议
简单项目/新手 → npm
大型项目/Monorepo → pnpm
各自优势对比
npm 的优势
- 免安装/默认自带:随 Node.js 一起安装,无需额外配置,适合新手与简单项目。
- 生态兼容性最好 :历史最悠久,极个别老旧极端依赖包在
npm的扁平化node_modules结构下兼容性最为稳妥。 - 绝对成熟稳定 :拥有最庞大的用户群体和无数次版本迭代。 [1](https://zhuanlan.zhihu.com/p/1929579988274902650), [2](https://www.runoob.com/nodejs/nodejs-npm.html)
pnpm 的优势
- 极致节省磁盘:采用全局单一存储与硬链接/软链接技术,相同依赖在多项目中不重复占用空间。
- 安装速度极快:省去重复下载和解压,大项目及离线冷启动速度显著提升。
- 杜绝幽灵依赖 :非扁平化目录结构,代码无法引用未在
package.json中声明的包,安全性更高。 - 原生支持 Monorepo:自带优秀的 Workspace 功能,非常适合多包大型仓库。
差异对比
持续集成与生产环境(CI/CD)
| 操作场景 | npm 命令 | pnpm 命令 | 说明 |
|---|---|---|---|
| CI 环境严格安装 | npm ci |
pnpm install --frozen-lockfile |
核心平移。严格对比 lock 文件,不允许更新,锁定版本。 |
| 仅安装生产依赖 | npm i --production |
pnpm install --prod |
部署阶段使用,不安装 devDependencies。 |
依赖管理与检查
| 操作场景 | npm 命令 | pnpm 命令 | 说明 |
|---|---|---|---|
| 查看依赖版本 | npm list / npm ls |
pnpm list / pnpm ls |
列出当前安装的包结构。 |
| 检查过期依赖 | npm outdated |
pnpm outdated |
对比远程仓库,寻找可以升级的依赖。 |
| 漏洞安全审计 | npm audit |
pnpm audit |
检查项目依赖是否存在已知安全漏洞。 |
| 修改远程包源码 | 无直接对应命令 | pnpm patch <pkg> |
极其实用的高级功能,可直接给 node_modules 中的包打补丁。 |
缓存与存储维护
| 操作场景 | npm 命令 | pnpm 命令 | 说明 |
|---|---|---|---|
| 清理缓存/全局存储 | npm cache clean --force |
pnpm store prune |
pnpm 用于清理全局存储中未被引用的无效孤立包,释放磁盘空间。 |
| 检查存储状态 | npm cache verify |
pnpm store status |
验证存储的完整性。 |
多包管理(Monorepo)与执行
npm 的多包命令较为局限(需要借助 lerna 或通过 --workspace 参数),而 pnpm 原生支持强力的多包管理过滤器。
| 操作场景 | npm 命令 | pnpm 命令 | 说明 |
|---|---|---|---|
| 指定子包安装依赖 | npm i <pkg> -w <sub-pkg> |
pnpm --filter <sub-pkg> add <pkg> |
在 Monorepo 仓库中,为特定的子包添加依赖。 |
| 所有子包批量执行 | npm run <script> --workspaces |
pnpm -r run <script> |
-r 代表 recursive(递归),批量执行所有子包的脚本。 |
基础与高级命令速查大表(全景对比)
| 场景 | npm 命令 | pnpm 命令 |
|---|---|---|
| 项目初始化 | npm init |
pnpm init |
| 普通安装 | npm install / npm i |
pnpm install / pnpm i |
| 添加依赖 | npm i <pkg> |
pnpm add <pkg> |
| 开发依赖 | npm i -D <pkg> |
pnpm add -D <pkg> |
| 全局安装 | npm i -g <pkg> |
pnpm add -g <pkg> |
| 卸载依赖 | npm uninstall <pkg> |
pnpm remove <pkg> / pnpm rm |
| 运行脚本 | npm run <script> |
pnpm run <script> 或 pnpm <script> |
| 按需免安装执行 | npx <pkg> |
pnpm dlx <pkg> |
| 更新依赖 | npm update |
pnpm update |
| 锁版本发布 | npm publish |
pnpm publish |
| 链接本地包调试 | npm link |
pnpm link |
性能与资源对比(参考 pnpm 官方 benchmark)
下面这张柱状图基于 pnpm 官方 benchmark 数据,直观对比 npm 与 pnpm 在安装速度 、磁盘占用 和依赖数量三个维度的差异(数值为相对比例,npm 基准 = 100):
#mermaid-svg-7mK61LThL2m4OiiB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7mK61LThL2m4OiiB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7mK61LThL2m4OiiB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7mK61LThL2m4OiiB .error-icon{fill:#552222;}#mermaid-svg-7mK61LThL2m4OiiB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7mK61LThL2m4OiiB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7mK61LThL2m4OiiB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7mK61LThL2m4OiiB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7mK61LThL2m4OiiB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7mK61LThL2m4OiiB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7mK61LThL2m4OiiB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7mK61LThL2m4OiiB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7mK61LThL2m4OiiB .marker.cross{stroke:#333333;}#mermaid-svg-7mK61LThL2m4OiiB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7mK61LThL2m4OiiB p{margin:0;}#mermaid-svg-7mK61LThL2m4OiiB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} npm vs pnpm 性能对比(npm 基准 = 100) 安装速度 磁盘占用 依赖数量 100 90 80 70 60 50 40 30 20 10 0 相对值
说明:柱状图中每组左侧为 npm(基准 100),右侧为 pnpm。数值越低代表表现越好(安装耗时更短、磁盘占用更少、依赖数量更精简)。
图表解读 :在 pnpm 官方 benchmark 中,pnpm 的安装速度约为 npm 的 2 倍以上 (耗时约为 npm 的 1/4),磁盘占用仅为 npm 的 1/5 左右 ,依赖数量也因硬链接去重而大幅精简(约为 npm 的 40%)。这主要得益于 pnpm 的全局单一存储 + 硬链接/软链接 机制------相同版本的依赖只需在磁盘上保存一份,其余项目通过链接引用,从而同时实现极速安装 与极低磁盘占用。对于依赖繁多的中大型项目,这种优势会随依赖规模扩大而愈发明显。
npx = pnpm exec + pnpm dlx
在功能定位上,npx 确实相当于 pnpm exec + pnpm dlx 的合体。
为了让你一目了然,这里为你梳理出最精简的核心对比:
核心功能拆解
npx= "全能执行器"(本地有就用本地,本地没有就去下载)。pnpm exec= "本地执行器" (只在本地找,找不到就报错)。pnpm dlx= "远程下载器" (不看本地,强制去下载/调取全新临时包)。
精简对比表
| 执行命令 | 优先检查本地? | 本地没有时会下载吗? | 核心设计理念 |
|---|---|---|---|
npx |
会 🟢 | 会 🟢 | 方便至上:不管在哪,能跑就行。 |
pnpm exec |
会 🟢 | 不会 ❌ | 本地安全:只跑项目内的工具,绝不乱下。 |
pnpm dlx |
不会 ❌ | 会 🟢 | 严格隔离:确保拿到最新/干净的包,不污染项目。 |