pnpm
根据官网的介绍 p
是单词 performant
的缩写,所以 pnpm
可以理解为 performant npm
。
pnpm
主要有以下优点:
节省:节省硬盘空间,解决幽灵依赖。
快速: pnpm
比其他包管理工具快两倍;
高效: node_modules
中的文件链接自特定的内容寻址存储库;
支持monorepo: pnpm
内置了对存储库中的多个包的支持;
严格: pnpm
默认创建一个非平铺的 node_modules
,因此代码不能访问任意包;
软连接和硬连接的介绍
pnpm使用软连接器和硬连接器(在Windows中使用的连接器)来连接相同的库文件夹。这意味着:
连接的库文件夹至少包含一个名为 package.json
的文件和一个名为 .pnpm-cache
的临时文件夹。
连接后的文件夹也包括名为 node_modules
的文件夹和名为 .pnpm-store
,在连接成功后,文件夹也应生成一个名为 .pnpm-cache
的临时文件夹,以便于重新连接时使用。
在维基百科中,软链接是被这样定义的:
符号链接也称为软链接,它是一类特殊的文件,其包含有一条以绝对路径或者相对路径的形式执行其他文件或者目录的引用。
一个符号链接文件仅包含有一个文本字符串,其被操作系统解释为一条指向另一个文件或者目录的路径。它是一个独立文件,其存在并不依赖于目标文件。如果删除一个符号链接,它指向的目标文件不受影响,如果目标文件被移动、重命名或者删除,任何指向它的符号链接仍然存在,但是它们将会指向一个不复存在的文件。
在维基百科中,硬链接是被这样定义的:
硬链接是计算机文件系统中的多个文件平等地共享同一个文件存储单元。硬链接必须在同一个文件系统中;一般用户权限下的硬链接只能用于文件,不能用于目录,因为其父目录就有歧义了。删除一个文件名字后,还可以用其它名字继续访问该文件。硬链接只能用于同一个文件系统,不能用于不存在的文件。
软链接和硬链接用我个人的理解,可以有以下代码所示:
// 硬链接
const hard = {
nickname: "moment",
age: 20,
address: "北京",
};
// 软链接
const soft = hard;
这里的 soft
变量通过 `hard 变量最终可以访问到这个对象的实际地址。
节约磁盘空间并提升安装速度
当我们使用 npm 进行不同的项目开发的时候,依赖都会重复安装一次,而在使用 pnpm 时,依赖会被存储在内容可寻址的存储中,所以:
如果你用到了某依赖项的不同版本,只会将不同版本间有差异的文件添加到仓库。例如,如果某个包有100个文件,而它的新版本只改变了其中1个文件。那么 pnpm update
时只会向存储中心额外添加1个新文件,而不会因为仅仅一个文件的改变复制整新版本包的内容。
所有文件都会存储在硬盘上的某一位置,当软件包被被安装时,包里的文件会硬链接到这一位置,而不会占用额外的磁盘空间,这允许你跨项目地共享同一版本的依赖。
创建非扁平的 node_modules
在执行 pnpm install
后会有这样一句话:
翻译过来是:包是从全局 store
硬连接到虚拟 store
的,这里的虚拟 store
就是 node_modules/.pnpm
,所有的依赖都在这里铺平了,都是从全局 store
硬连接过来的,然后包和包之间的依赖关系是通过软链接组织的。下面是官方的说明图:
具体例子,下面的 node_modules/@eslint
是符号链接,软链接。
那么 @eslint
的真实位置在哪呢?,答案在:node_modules/.pnpm/@eslint+eslintrc@1.4.1/node_modules/@eslint
,如下图。
当然的 node_modules/.pnpm
下其他包再引用 @eslint
也是软链接。
在这里我们也可以知道 .pnpm/ 文件夹的用途了,它以平铺的形式存储着所有的依赖包.所以每个包都可以在这种模式命名的文件夹中找到:
.pnpm/<name>@<version>/node_modules/<name>
这种方式称之为虚拟存储目录,这个平铺的结构避免了 npm
之前版本创建的 node_modules
引起的长路径问题,又与之后的版本创建的平铺的 node_modules
不同的是,它保留了包之间的相互隔离。这种方式可以优先避免像 npm
的扁平结构带来的幽灵依赖。
性能对比
action | cache | lockfile | node_modules | npm | pnpm | Yarn | Yarn PnP |
---|---|---|---|---|---|---|---|
install | 33.8s | 18s | 20.3s | 44.7s | |||
install | ✔ | ✔ | ✔ | 2.1s | 1.4s | 2.6s | n/a |
install | ✔ | ✔ | 9.1s | 4.9s | 7.8s | 1.7s | |
install | ✔ | 13.5s | 8.4s | 14.1s | 7.7s | ||
install | ✔ | 15s | 15.7s | 14.2s | 37.5s | ||
install | ✔ | ✔ | 2.5s | 2.8s | 8.8s | n/a | |
install | ✔ | ✔ | 2s | 1.4s | 8.7s | n/a | |
install | ✔ | 2.5s | 9.9s | 14.7s | n/a | ||
update | n/a | n/a | n/a | 8.9s | 11s | 7s | 15.6s |