快速掌握pnpm使用命令和实现原理

7,895 阅读3分钟

pnpm也称高性能npm,相比npm、yarn优势在于节省磁盘空间并提升安装速度

安装

在 POSIX 类系统上,即使尚未安装 Node.js,也可以使用以下脚本安装 pnpm:

   curl -fsSL https://get.pnpm.io/install.sh | sh -
   // 如果没有安装 curl,可以使用 wget
   wget -qO- https://get.pnpm.io/install.sh | sh -

这里解释下POSIX,即可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),简单理解为一个标准,遵循该标准的系统首先就是Unix和Linux,其中苹果的操作系统也是Unix-based同样遵循该标准

在 Windows 系统上(PowerShell):

   iwr https://get.pnpm.io/install.ps1 -useb | iex

使用 npm

   npm install -g pnpm

常用命令

命令解释
pnpm -v查看已安装的pnpm的版本
pnpm install xxx/pnpm i xxx安装依赖
pnpm run xxx运行package.json中scripts脚本
pnpm config get registry查看源
pnpm config set registry <淘宝源或私服>切换源
pnpm add xxx安装依赖包到 dependencies
pnpm add -D xxx安装依赖包到devDependencies
pnpm update xxx/pnpm up xxx更新依赖包
pnpm remove xxx删除依赖包

实现原理

pnpm结合软硬链接与新的依赖组织方式,大大提升了包管理的效率,同时解决了幽灵依赖问题

在分析该原理图前首先我们先了解一些操作系统的知识以及幽灵依赖

  • 硬链接 - hard link

就是一个文件的一个或多个文件名。再说白点,所谓链接无非是把文件名和计算机文件系统使用的节点号链接起来。因此我们可以用多个文件名与同一个文件进行链接,这些文件名可以在同一目录或不同目录-百度百科

通过硬链接,不会产生额外的磁盘占用,并且,两个文件都能找到相同的磁盘内容

硬链接.png

文件A与文件B有相同引用,通过硬链接,不会产生额外的磁盘占用,修改文件A,文件B也同时改变

  • 软链接 - Symbolic links/Soft links

软链接又叫符号链接,这个文件包含了另一个文件的路径名。可以是任意文件或目录,可以链接不同文件系统的文件。-百度百科

软链接.png 如果为某个文件或文件夹A创建符号连接B,则B指向A

  • 幽灵依赖

即某个包没有被安装在package.json里,但是用户却能够引用到这个包,原因是在npmv3版本以后,一个库只要被其他库依赖,哪怕没有显式声明在package.json中,会被安装在node_modules的一级目录里

pnpm官网提供的原理图:

node-modules-structure-8ab301ddaed3b7530858b233f5b3be57.jpg

  • node_modules 下安装包结构为树形,避免了幽灵依赖,同时以软链接方式将内容指向 node_modules/.pnpm目录下具体文件
  • .pnpm 目录以打平结构管理每个版本包的源码内容,以硬链接方式指向 pnpm-store 中的文件地址,所有依赖包都安装在全局目录 ~/.pnpm-store/v3/

npm/pnpm目录对比

使用npm安装antd后目录结构:

npm init
npm install antd

npm1.png npm安装的包在node_modules目录下被打平

使用pnpm安装antd后目录结构:

pnpm init
pnpm install antd

pnpm1.png pnpm安装的包在node_modules目录下只有package.json中安装的依赖包以及.pnpm,依赖包通过软链方式指向.pnpm目录里的文件

查看pnpm store全局存储目录的路径

pnpm store path

npm/yarn项目转pnpm

删除node_modules

rm -rf node_modules

基于项目中lock文件生成pnpm-lock.yaml

pnpm import

安装依赖

pnpm install --frozen-lockfile

--frozen-lockfile相当于npm ci生成依赖,防止没有lock文件意外升级依赖包

总结

pnpm依赖文件通过三次寻址方式找到下载资源

第一次通过package.json中安装依赖找到node_modules目录下依赖包,即node_modules/antd

第二次通过node_modules/antd 软链接 node_modules/.pnpm/antd@4.23.1/node_modules/antd 解决了代码重复引用的问题;

第三次通过node_modules/.pnpm/antd@4.23.1/node_modules/antd 硬链接 ~/.pnpm-store/v3/files/00/xxx 已经脱离当前项目路径,指向一个全局统一管理路径,这种方式符合 node_modules 默认寻址方式,节省了磁盘空间,也解决了幽灵依赖