pnpm是什么

快速、节省磁盘空间的包管理器。

开发pnpm的初衷

节省磁盘空间

  使用 npm 时,如果你有 100 个项目都用到了同一个依赖,那这 100 个项目会各自保存一份该依赖的副本,相当于磁盘上有 100 份相同的文件,很占空间
  使用 pnpm,依赖将存储在内容可寻址存储中,通过‘硬链接’的方式让各个项目使用,不额外消耗磁盘空间,实现了项目共享。如果你依赖于不同版本的依赖,则仅将不同的文件添加到存储中。如原本有 100 个文件,新版本只改了 1 个文件,pnpm 不会把整个新版本重新存一遍,只会把那 1 个改动的新文件添加到存储里,剩下的还是用之前的,大大减少了重复存储。

提高安装速度

pnpm 分三个阶段执行安装:
  1. 依赖解析。识别所有必需的依赖并将其提取到存储中。
  2. 目录结构计算。node_modules 目录结构是根据依赖计算出来的。
  3. 链接依赖。所有剩余的依赖都会从存储中获取并硬链接到 node_modules
这种方法比解析、获取所有依赖并将所有依赖写入 node_modules 的传统三阶段安装过程要快得多。

创建非扁平 node_modules 目录

使用 npm 或 Yarn Classic 安装依赖时,所有包都会提升到模块目录的根目录。这就导致一个问题,源代码可以访问未作为依赖添加到项目中的依赖。

PS:幽灵依赖,你的代码可能会用到一些本不该能访问的东西,Node.js 在 require 一个模块时,会沿着目录树向上递归查找 node_modules 文件夹。因此,无论是直接依赖还是被提升到根目录的子依赖,都可以被项目的源代码直接找到并引入。一旦间接依赖的版本发生变更、被移除或其在依赖树中的位置改变(如包管理工具调整依赖解析逻辑),原本可访问的 “幽灵依赖” 将无法被找到,导致项目运行时出现模块缺失错误,破坏了依赖管理的确定性和代码的稳定性。。

默认情况下,pnpm 使用符号链接仅将项目的直接依赖添加到模块目录的根目录中。解决了传统工具(npm/yarn)因“扁平化”导致的依赖混乱和安全隐患问题,实现了更严格、更高效的管理。

PS:所有间接依赖都被严格地隔离在 .pnpm 子目录下的虚拟存储层中,并且其访问权限受到限制。

pnpm 的 node_modules 布局使用符号链接来创建依赖的嵌套结构。 node_modules 内每个包的每个文件都是到内容可寻址存储的硬链接。

额外帮助理解知识点

文件存储

现代文件系统 Unix/Linux等中,文件的存储被拆分为两个部分,inode与数据块。
inode:存储了文件的元信息,如权限、创建时间、文件大小以及指向数据块的指针,引用计数(有多少个文件名指向这个inode)。每个inode唯一。
数据块:存储文件的实际内容(如文本、图片等)。数据块的位置由inode记录,用户通过文件名访问文件时,系统先找到类似的inode,再通过inode找到数据块。
文件名类似于一个“标签”,这个标签指向一个inode 。例如,创建一个文件 a.txt,系统就为你分配一个 inode(比如 #1001)和一块磁盘空间来存储内容。文件名 a.txt 指向这个 inode #1001。

什么是硬链接

硬链接(Hard Link)是文件系统提供的一种共享 inode 的机制,本质是给同一个 inode 新增一个文件名标签。
假设你为 a.txt 创建一个硬链接b.txt。现在这两个文件名都指向完全相同的 inode #1001,两者也指向同一数据块(修改b.txt, a.txt也会变化,因为是同一个内容)。 inode 的 "引用计数" 从 1 变为 2(表示有两个文件名指向它)。
删除不影响数据,直到引用计数为0, 删除 a.txt 时,只是删除目录中 a.txt → inode 的映射,引用计数从 2 减为 1, b.txt 仍有效 ,只有当 b.txt 也被删除,引用计数变为 0,系统才会标记数据块为 "可释放"(实际删除数据)。
不能为目录创建硬链接(避免在文件系统中形成循环引用),也不能跨文件系统或分区创建(因为 inode 编号是分区内唯一的)

什么是软链接

软链接(符号链接)是一个独立文件,内容是目标文件的路径,多个inode,可以理解为“快捷方式” 假设你为 a.txt 创建一个软链接 c.txt。系统会为这个软链接本身分配一个新的 inode(比如 #1003),这个 inode 指向的数据块里存储着字符串 "a.txt"。

为什么使用硬链接而非软链接

如果路径变动,如删除原文件,软链接会失效(断链)而 硬链接直接指向 inode,与路径无关,只要 inode 未被删除,硬链接仍能正常访问文件。

内容可寻址存储

内容可寻址存储(Content-Addressable Storage)是一种以文件内容而非路径 / 名称作为唯一标识的存储方式。意味着文件的存储路径不是由它的名字决定,而是由其内容的哈希值计算得出的。

常用安装方式

在window上,使用独立脚本

使用powerShell

Invoke-WebRequest https://get.pnpm.io/install.ps1 -UseBasicParsing | Invoke-Expression

使用npm包管理器

提供了两个 pnpm CLI 包,pnpm 和 @pnpm/exe。pnpm是需要 Node.js 才能运行。@pnpm/exe与 Node.js 一起打包成可执行文件,可以在未安装 Node.js 的系统上使用。

npm install -g pnpm@latest-10
npm install -g @pnpm/exe@latest-10

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐