| 特性 | npm | yarn | pnpm |
|---|---|---|---|
| 存储结构 | 每项目独立存依赖,层层嵌套,目录大。 | 扁平结构,多个版本仍需嵌套,存储略优化。 | 使用全局 .pnpm-store,项目通过硬链接引用,节省空间。 |
| 安装机制 | 串行下载并写入 node_modules,速度慢。 |
并行安装,加快依赖写入速度。 | 并行 + 去重 + 硬链接,减少重复写入和磁盘 I/O。 |
| 缓存方式 | 包存于 .npm/_cache,安装仍需解压复制。 |
下载压缩包到 .yarn/cache,仍需解压。 |
内容寻址缓存,直接链接使用,无解压、无复制。 |
| 锁文件 | package-lock.json,结构详尽但大,合并冲突复杂。 |
yarn.lock,结构简洁,版本控制友好。 |
pnpm-lock.yaml,基于内容哈希,唯一性强,冲突少。 |
| node_modules | 扁平 + 自动依赖提升,容易产生“幽灵依赖”问题。 | 同样扁平,但支持配置禁用某些提升。 | 每依赖独立路径管理,更接近真实包关系,可选 hoist,默认更安全。 |
| 工作区支持 | v7 起支持 workspaces,功能基础,缺少工具链集成。 | 原生支持,可统一依赖、构建、执行脚本,适合 monorepo。 | 原生支持 + -r/-F 命令支持递归构建、过滤执行,最强 monorepo 支持。 |
幽灵依赖,项目当前引用的 a 包可能是作为 b 包的依赖而下载的,哪一天 b 包不依赖 a 包了,项目就会运行失败
并非完全平铺,同一包存在多版本时依旧嵌套
幽灵依赖: 有些包没有在 package 内显示引用,而是作为依赖包的依赖被下载,平铺在 modules 内
因而这些(package 内)看不见的依赖包可以被开发者正常引用
pnpm 有了更严格的要求,必须显示引用
回归使用多层嵌套依赖,以解决幽灵依赖问题
项目中依赖包全部使用软硬连接,包只在盘符根目录.pnpm-store 存一份,以解决重复下载包的问题
node_modules 内的包,与 package 内的引用一一对应,且多出一个.pnpm
.pnpm 内平铺了所有 package 包的依赖 及其 多层嵌套依赖,同 npm、yarn
.pnpm 平铺的包全部 硬链接 自全局 store
.pnpm 平铺的包相互 软连接 实现相互依赖,借此以平铺做到多层嵌套相同效果
优点: 安装快,删除快,节省磁盘,多项目共享缓存,
pnpm 是并发调度下载
pnpm 原生支持 monorepo
pnpm-lock.yaml 结构更清晰
workspaces 机制专为 monorepo 设计,处理包依赖拓扑结构更加高效
待更新