[分享]关于 PNPM
简单、好用的pnpm,快到碗里来
高效利用磁盘空间
假如磁盘中有五个vue@2.7项目,当进行npm install
的时候,node_modules 中会存放一个2.5Mb大小的包,五个项目就会存放5个2.5Mb的包。
使用pnpm的话,五个项目只会占有2.5Mb的包。
首先它会在磁盘根目录创建一个 ~/.pnpm-store
文件夹,用于统一存放管理依赖,依赖安装完成后,然后到项目中的node_modules/.pnpm
中生成依赖包的硬链接,再通过软链接的方式把对应的依赖包软链接到 node_modules,因此我们节约磁盘空间并提升安装速度。
pnpm-pen
解决依赖分身
当我们有一个这样的项目:
└── node_modules
├── A
└── node_modules
└── Z@1.0.0
└── B
└── node_modules
└── Z@2.0.0
└── C
└── node_modules
└── Z@2.0.0
├── package.json
└── yarn.lock
使用npm < 3
:
在安装依赖包之后,会将依赖以树形结构存储在 node_modules 中,子依赖会继续安装到依赖的node_modules中,以此循环。这种方式会重复安装项目的包到不同的路径下,造成磁盘空间浪费,同时过深的层级在windows下会造成无法直接删除的问题。
使用npm > 3 or yarn
:
npm为了重复安装包和层级过深的问题,npm3和yarn使用了扁平化依赖的方式来解决问题。
通过将依赖拍平到node_modules下,配合node require 机制向上查找需要的包。这个方案解决了重复包安装到问题以及层级过深的问题,但同时带来了幻影依赖问题。
使用pnpm
:
pnpm 巧妙的通过硬链接 + 软链接结合的方式,实现了树结构的 node_modules,并解决了依赖幻影、依赖分身和层级过深的问题。
解决幽灵依赖
使用npm>=3或者yarn进行依赖安装时,会使用扁平化的方式进行依赖管理。
当我们yarn add vite
时,node_moduels 目录结构会是这样的,这时候我们在项目中`import 'esbuild' 代码不会报错(not cool)。
├── node_modules
│ ├── esbuild
│ ├── esbuild-darwin-64
│ ├── fsevents
│ ├── function-bind
│ ├── has
│ ├── is-core-module
│ ├── nanoid
│ ├── path-parse
│ ├── picocolors
│ ├── postcss
│ ├── resolve
│ ├── rollup
│ ├── source-map-js
│ ├── supports-preserve-symlinks-flag
│ └── vite
├── package.json
└── yarn.lock
当我们pnpm add vite
时,node_moduels 目录结构会是这样的,这时候我们在项目中import 'esbuild'
代码会报错,找不到 esbuild
。
└── node_modules
├── .bin
├── .pnpm
│ ├── esbuild-darwin-64@0.14.49
│ ├── esbuild@0.14.49
│ ├── fsevents@2.3.2
│ ├── function-bind@1.1.1
│ ├── has@1.0.3
│ ├── is-core-module@2.9.0
│ ├── nanoid@3.3.4
│ ├── node_modules
│ ├── path-parse@1.0.7
│ ├── picocolors@1.0.0
│ ├── postcss@8.4.14
│ ├── resolve@1.22.1
│ ├── rollup@2.77.0
│ ├── source-map-js@1.0.2
│ ├── supports-preserve-symlinks-flag@1.0.0
│ └── vite@3.0.2
└── vite -> .pnpm/vite@3.0.2/node_modules/vite -> 软连接
总结
随着vue3、vite仓库和vue生态项目也切换到了pnpm,我也尝试了一段时间。把个人项目都迁移到了pnpm生态上,迁移成本低,好上手,速度快、体积小,真香,希望pnpm越发普及!
如果老的项目依赖存在幽灵依赖导致无法正常运行,可以毫不羞耻的在项目 .npmrc 里写一行 shamefully-hoist=true。
拓展阅读 & 参考资料
pnpm 官方文档
node_modules 困境
迁移常见的问题
为什么 vue 源码以及生态仓库要迁移 pnpm?
开发脚手架可以参考一下vite的pr