开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
什么是pmpm
pnpm官网介绍:快速的,节省磁盘空间的包管理工具。pnpm官网
pnpm特点
- 更快
- 更小的磁盘占用
- 软连接,硬链接
- 重复的依赖项不会额外占用空间
pnpm vs npm、yarn的区别
下图为pnpm官网给出的pnpm、npm、yarn、yarn PnP在不同场景安装速度的对比。
从图片可以看出。pnpm在除update的场景。其余场景时间均快于其他几个包管理工具。尤其实在手机安装的时候。时间差异明显。
npm、yarn的痛点
- 幽灵依赖(项目中使用了没有被定义在package.josn中的依赖)
- 多个依赖间版本不同
在包管理工具发展的历史中。持续存在以下几个痛点。
- 如何快速获取依赖包
- 如何快速下载依赖包
- 如何快速把依赖包写入硬盘
在npm@3版本后。加入了扁平化node_modules。根据依赖包引入的先后顺序。把依赖包扁平安装在node_modules目录下。遇到相同依赖包,不同依赖版本的情况。则会将后续不同版本的依赖包。维持嵌套的形式。安装在对应包的node_modules下面。
那么pnpm是怎么处理的呢?
pnpm原理
- 使用pnpm安装依赖后。会在node_modules下面生成一个.pnpm的文件。
- 在.pnpm内会将所有的依赖性包括相同依赖包的不同版本。全部放在.pmpm/node_modules下面。
- 如下node_modules根目录下的foo与.pnpm/foo@1.0.0下的bar都是通过软连接的方式。指向foo。
node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ └── bar -> <store>/bar
└── foo@1.0.0
└── node_modules
├── foo -> <store>/foo
└── bar -> ../../bar@1.0.0/node_modules/bar
遇到peer,则会为每一个不同的peer创建不同的依赖组。如下所示。
node_modules
└── .pnpm
├── foo@1.0.0_bar@1.0.0+baz@1.0.0
│ └── node_modules
│ ├── foo
│ ├── bar -> ../../bar@1.0.0/node_modules/bar
│ ├── baz -> ../../baz@1.0.0/node_modules/baz
│ ├── qux -> ../../qux@1.0.0/node_modules/qux
│ └── plugh -> ../../plugh@1.0.0/node_modules/plugh
├── foo@1.0.0_bar@1.0.0+baz@1.1.0
│ └── node_modules
│ ├── foo
│ ├── bar -> ../../bar@1.0.0/node_modules/bar
│ ├── baz -> ../../baz@1.1.0/node_modules/baz
│ ├── qux -> ../../qux@1.0.0/node_modules/qux
│ └── plugh -> ../../plugh@1.0.0/node_modules/plugh
├── bar@1.0.0
├── baz@1.0.0
├── baz@1.1.0
├── qux@1.0.0
├── plugh@1.0.0
pnpm在项目中的使用
使用下列命令可以直接创建一个pnpm、vue3、ts的项目。在项目中体验pnpm。
pnpm create vite my-vue-app --template vue-ts
pnpm的缺点
- 没有独立的node_modules。调试某一包。可能会造成全局污染。
- 软连接的创建也需要消耗磁盘空间。
如何将pnpm改为和npm、yarn相同的node_modules结构
在项目根目录创建文件.npmrc 文件内写入 node-linker=hoisted
删除现有的node_modules。重新pnpm install。
安装完成之后,查看node_modules目录就能发现。和之前的npm安装一样的目录结构。