pnpm梳理

用户头像
作者:新鲜噩梦
简介:little笔记全栈作者
创建于:2025-09-09 16:10:34字数:5490
pnpm 相比 npm/yarn 来说,最大的进步就是:可以复用多个项目中重复的依赖,节省磁盘空间。
如果使用npm/yarn安装依赖,当电脑中存在多个前端项目时,即使每一个项目都是安装的相同的依赖包,每个项目中也都会存在独立的一份依赖,这就很不科学,浪费磁盘空间。
在早期的npm中,打包的规则如下:
假设一个项目安装了依赖
json
"dependencies": { "webpack": "^xx", "babel": "^xx", }
那么安装完就是这样
js
# 项目根目录 └── node_modules/ # 项目依赖根目录 ├── webpack/ # 项目直接依赖:webpack │ └── node_modules/ # webpack的嵌套依赖 │ ├── aaa/ # webpack依赖的aaa包 │ ├── bbb/ # webpack依赖的bbb包 │ └── anymatch/ # webpack依赖的anymatch包(第一次存储) └── babel/ # 项目直接依赖:babel └── node_modules/ # babel的嵌套依赖 ├── ccc/ # babel依赖的ccc包 └── anymatch/ # babel依赖的anymatch包(第二次存储,重复)
注意,webpack 和 babel 都引用了一个 anymatch 的依赖,但是这个依赖被创建了2次,占了2份的磁盘空间,这显然是不科学的。
产生的问题:
  1. 公共的依赖会复制很多次,会占据比较大的磁盘空间。
  2. windows 的文件路径长度有限制,嵌套层级过深很容易导致系统错误。
为了解决这两个问题,后面的版本中 npm/yarn 就改成了平铺的模式。
那么安装完就是这样
js
# 项目根目录 └── node_modules/ # 项目依赖根目录 ├── webpack/ # 项目直接依赖:webpack ├── babel/ # 项目直接依赖:babel ├── aaa/ # webpack的依赖(被平铺) ├── bbb/ # webpack的依赖(被平铺) ├── ccc/ # babel的依赖(被平铺) └── anymatch/ # 共享依赖(只存储一次,但暴露为顶层依赖)
这平铺确实解决了多次创建依赖的问题。
新的问题:
  1. 项目中的dependencies没有:anymatch,aaa, bbb, ccc,但是项目中却可以直接 import 使用,这就是幽灵依赖问题。
  2. 即使 npm/yarn 使用平铺的模式能节省一部分空间,那也只局限于单个项目中。多个工程项目中,假设每一个工程都引入了axios这个包,那么每个工程都会有一份独立的axios的平铺依赖,所以平铺这种模式也只是解决了一个小问题而已。
为了解决新的问题,pnpm出现。
pnpm优势
  1. 可以复用多个项目中重复的依赖,节省磁盘空间
  2. 快速,比其他包管理器快2倍。
  3. 高效,node_modules 使用软硬链接进行寻址存储库。
  4. 支持 monorepos,pnpm内置支持单仓多包。
  5. 严格,pnpm创建的node_modules不是平铺的,而是有层次的嵌套依赖。防止幽灵依赖的问题。

pnpm 如何实现这些优点的

了解pnpm之前,必须前置理解一些概念。
软连接和硬链接
  • 软连接(符号链接):soft link 或 symbolic link(相当于电脑的创建的快捷方式)
    是一类特殊的文件。
    其包含有一条以绝对路径或相对路径的形式指向其他文件或者目录的引用。
    可以链接文件夹。
  • 硬链接:hard link
    是电脑文件系统中多个文件共享一个文件存储单元。
    删除一个文件名后,还可以用其他名字继续访问。
    只可以链接文件,不可以链接文件夹。
下图:左-软连接,右-硬链接
F8C31F73-6665-411B-9F10-5A5F8574904A
硬链接
当磁盘中存在一份Data,可以是视频文件、word文档等。这个Data硬链接可以创建多个,并且每一个硬链接都可以对这个Data进行读取和修改操作,并且修改后其他的硬链接的Data也同步更新变化,因为他们从根本上就是链接的同一个数据。
75F98796-C09A-41CA-A4DE-E028041CC0A1
要注意和复制粘贴区分:
复制粘贴或者说是copy,是把磁盘数据复制一份写入了磁盘,此时磁盘是两份数据了,而硬链接只是一份数据。复制粘贴是真正的磁盘数据备份。
DA6384E7-472E-4F0A-AAF8-23CBF9E3D3C1
使用 ln 命令创建硬链接
当其中一个文件修改内容时,另一个文件也会实时同步更新内容。
以下使用mac做的演示:
使用 ln 1.js 1_hard.js 命令创建出一个 1_hard.js硬链接文件,如下图:
1E2DA619-D77B-48E2-BDC2-AFD5467F00E4
当改变1_hard.js文件的内容并保存时,1.js的内容也同步改变了,如下图:
713590BC-E26D-4582-A207-BA83FBAD8DAB
软链接
软连接参考windows下的快捷方式
注意:软连接可以连接到文件夹!这一点和硬链接不同。
如果软连接到文件夹(window 使用命令 mklink /d xxx xxx),整个文件夹的内容都会被连接一份,像是复制了一份文件夹。
00EEF412-6480-430B-90ED-B688D4C2CAAC
ln -s 做演示
E0C76DEA-7039-445E-89F1-B3C7FCE1FB60
12662096-FB0E-4EE2-B237-65E562874A74
在Mac和windows下:
  1. 当修改2_soft.js时,2.js也被实时修改了。
  2. 当修改2.js时,2_soft.js没有被实时修改,重新打开2_soft.js就可以看到被修改的内容了。
  3. 当删除2.js时,2_soft.js 为不可用状态。
了解完了软、硬链接,看看pnpm是如何使用它们创建依赖目录的
在mac系统上使用pnpm安装了一个mime-types进行演示。
98b2817aa03244bff7f555a779e7df75
  1. 当项目中引用 mime-types 时,会去根目录的 node_modules 中寻找 mime-types 包,这包的文件夹是个软连接,软链接到 .pnpm 中的 mime-types@3.0.1 中的 mime-types
    这里使用软连接的好处就是防止多层嵌套的路径过长的问题,以及幽灵依赖的问题。
  2. 有一个专门存储npm包中各种小文件的目录,使用 pnpm store path 命令可以查看,/Users/baiwang/Library/pnpm/store/v10。 这个目录mime-types@3.0.1 中的 mime-types 的每一个文件都硬链接到这个目录中对应的文件,这样的好处就是所有相同的文件只有一份磁盘占用,非常节省磁盘空间。
  3. mime-types 引用的其他包,比如mime-db,会在同级目录下创建一个软连接的 mime-db,软链接到 .pnpm 中的 mime-types@1.54.0 中的 mime-db
  4. mime-types@1.54.0 中的 mime-db 同样也会硬链接到 /Users/baiwang/Library/pnpm/store/v10 这个目录。
通过 “统一存储目录 + 硬链接复用文件 + 软链接构建项目依赖路径” 的组合,pnpm 同时解决了 npm/yarn 面临的磁盘浪费、幽灵依赖、路径过长等问题,实现了高效、省空间且规范的依赖管理。
pnpm 的缺点
凡事都有两面性,通过询问ai和结合自身踩坑经验,总结出几个我认为比较重要的缺点:
1. 兼容问题
  • 在 Windows 系统或 WSL环境下,由于文件系统对链接的处理方式差异,有时可能会遇到权限问题或链接无法正常创建的情况。window对于pnpm确实不太友好,之前用过一阵win开发,使用pnpm是各种问题,最后就直接用npm了。
  • 许多库会在postinstall(安装后)脚本中执行依赖检查、文件生成等操作,但部分脚本可能硬编码了 npm 的node_modules路径(如假设依赖在../node_modules下),而 pnpm 的符号链接结构会导致这些脚本执行失败。我遇到过next.js 的 standalone 模式使用 pnpm 安装有问题。应该和这个有关,具体什么问题记不清了。
2. 脚本不能随意更改
  • 极少的时候,我们会去修改 node_modules 中的源码调试。但如果你修改了代码忘记还原了,问题就大了,因为整个电脑的前端项目的相同的第三方包都是引用同一批文件,其他的引用这个包的项目也会同步受到影响,一旦出现问题,很难找到问题的原因,所以千万不要给自己挖坑。

使用建议

  1. 新项目可以用pnpm,老的项目还是维持原样,不要随意迁移到pnpm,大概率会出现一些隐藏很深的bug。
  2. 开发环境使用pnpm,生产环境尽量还是使用npm,减少bug的出现,毕竟越精密的东西出问题的概率越高。
最后编辑于:2025-09-17 18:31:30
©著作权归作者所有,转载或内容合作请联系作者。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,little笔记系信息发布平台,仅提供信息存储服务。