简介
pnpm(performant npm)在 2017 年正式发布,定义为快速的,节省磁盘空间的包管理工具,开创了一套新的依赖管理机制。
优势
在介绍 pnpm 的优势之前,先来了解一下在以前 npm 和 yarn 的一些问题。
早期的 npm1、npm2 主要是采用简单的依赖递归方式,造成了高度的依赖嵌套,此时就造成了以下问题:
- 重复依赖嵌套地狱:重复大量的依赖嵌套,增加文件体积,造成了磁盘空间的浪费,使得安装速度过慢。
- 文件路径过长:window 系统下,路径过长会导致爆错,最多260多个字符。
之后 npm3 采用扁平化的方式,将依赖提升到根目录,解决了路径过长的问题,但是也带来了新的问题:
- 扁平化依赖算法耗时长
- 幻影依赖(Phantom dependencies):由于扁平化的方式使得依赖提升到了根目录,此时项目中的 package.json 并没有记录某个依赖,但是却能够在项目中使用,此时就造成了幻影依赖。幻影依赖可能会导致依赖之间的兼容问题,导致项目不能正常运行。
- 不确定性(Non-Determinism):由于依赖提升只能提升一个,如 A包安装B@1,C包和D包安装B@2,此时一个B依赖拥有两个版本,此时只提升一个,提升方式是谁先安装就先提升谁,这里可以就会造成生成环境和开发环境中的 node_modules 结构不同问题。
- 依赖分身(doppelgangers):A 和 B 依赖 C@1,D 和 E 依赖 C@2,由于依赖提升只能提升一个,所以无论提升 C@1 还是 C@2,都会造成包的重复安装。如下:
node_modules
├── A
├── B
├── C@1
├── D
└── node_modules
└── C@2.0
└── E
└── node_modules
└── C@2.0
之后 yarn 解决了 npm3 扁平化依赖算法耗时问题,就是通过 lock file,yarn 通过生成一个 yarn.lock 文件,来记录依赖的版本。
剩下的幻影依赖和依赖分身则在 pnpm 中得到了解决。
pnpm 通过内存寻址存储的方式,将依赖存储在系统磁盘上,依赖每个版本只会在系统中安装一次,使用时都会直接硬链接指向该依赖,解决了依赖分身问题,极大节省磁盘空间,并且加快安装速度。
之后在 pnpm 中模块通过软链接指向 node_modules 目录下的真实模块,解决了幽灵依赖问题。
硬链接是多个文件名指向同一个文件的实际内容,而软链接(符号链接)是一个独立的文件,指向另一个文件或目录的路径
- 硬链接 Hard link:硬链接可以理解为源文件的副本,项目里安装的其实是副本,它使得用户可以通过路径引用查找到全局 store 中的源文件,而且这个副本根本不占任何空间。
- 符号链接 Symbolic link:也叫软连接,可以理解为快捷方式,pnpm 可以通过它找到对应磁盘目录下的依赖地址。
总结
pnpm 是从全局 store 硬连接到 node_modules/.pnpm,然后之间通过软链接来组织依赖关系。
pnpm 的优势
pnpm 不仅提高了安装速度、节约了磁盘空间、避免了“依赖分身(doppelgangers)”和“幻影依赖(Phantom dependencies)”的问题。而且 yarn 支持的:安全、离线模式、更快的速度,pnpm 都支持,而且速度还要更快。
安装
npm i pnpm -g
常用命令
查看版本
pnpm -v
安装依赖
pnpm install [package-name]
卸载依赖
pnpm uninstall [package-name]
升级 pnpm
pnpm add -g pnpm to update
设置源
pnpm config get registry # 查看源
pnpm config set registry https://registry.npmmirror.com # 切换淘宝源
参考
- https://zhuanlan.zhihu.com/p/451025256
- https://www.jianshu.com/p/c427ed4c45e1
- https://zhuanlan.zhihu.com/p/646238140
- https://zhuanlan.zhihu.com/p/442133074
- https://github.com/npm/npm/issues/8826
- https://rushjs.io/pages/advanced/npm_doppelgangers/
- https://rushjs.io/pages/advanced/phantom_deps/
- npm、yarn、pnpm 性能对比
- https://juejin.cn/post/7242677017035751483
- https://juejin.cn/post/7339364757386559524