当前位置:网站首页>pnpm简介
pnpm简介
2022-07-30 08:47:00 【欧菲斯集团】
pnpm简介
pnpm是什么
和npm,yarn一样,pnpm是一个包管理工具。不一样的是,pnpm解决了npm和yarn一直都没有解决的痛点。在许多方面比npm和yarn更优秀。
pnpm对比npm/yarn的优点
- 更快速的依赖下载
- 更高效的利用磁盘空间
- 更优秀的依赖管理
更快速的依赖下载
根据官方提供的数据
从图上我们可以看出,pnpm平均比npm和yarn快上2~3倍。这一点在依赖的下载上额外明显。
更高效的利用磁盘空间
为什么说pnpm会比npm和yarn更高效的利用磁盘空间?
pnpm 有一个store的概念(是一块存储文件的空间,后面会说到),内部使用"基于内容寻址"的文件系统来存储磁盘上所有的文件,这一套系统的优点是:
不会重复下载依赖
举个例子 假设出现这么一个情况↓
你4个项目都依赖了express.js(第三方插件)。如果是npm/yarn的话,express.js就会被安装4个在你的磁盘空间当中。从而出现下面这个情况↓
但是pnpm 得益于"基于内容寻址"的文件系统,使用pnpm下载的文件不论被多少项目所依赖,都只会在磁盘中写入一次。后面再有项目使用的时候会采用硬链接的方式去索引那一块磁盘空间。
所以,在同样被多个项目依赖的时候,pnpm对磁盘的占用如下↓
如果有一天你所依赖的版本提升了。假设从[email protected]升级到了[email protected]。而[email protected]比[email protected]多了20个文件。这个时候pnpm并不会删除[email protected]再去重新下载[email protected]。而是复用[email protected]原本的磁盘内容。再在[email protected]的基础上增加20个文件形成[email protected]。
更优秀的依赖管理
在npm1和npm2的时候。依赖结构是这样的↓
node_modules
└─ 依赖A
├─ index.js
├─ package.json
└─ node_modules
└─ 依赖B
├─ index.js
└─ package.json
└─ 依赖C
├─ index.js
├─ package.json
└─ node_modules
└─ 依赖B
├─ index.js
└─ package.json
上面这种结构会导致哪些问题呢?让我们来分析下。
- 依赖包会被重复安装
- React实例无法共享
- 依赖层级太多问题
A依赖B,C也依赖B。也就是说B同时是A和C的依赖。这种情况下。B会被下载两次。
npm1和npm2的运行逻辑是,某一个包被其他包依赖N次,就需要被下载N次。也就是我们所说的重复安装。
npm3和yarn中平铺的结构依然存在的问题
上述npm1和npm2的这些问题在npm3+和yarn中得到了解决
从npm3开始。npm3和yarn都采用了"扁平化依赖"来解决上述问题。
node_modules
└─ 依赖A
├─ index.js
├─ package.json
└─ node_modules
└─ 依赖C
├─ index.js
├─ package.json
└─ node_modules
└─ 依赖B
├─ index.js
├─ package.json
└─ node_modules
所有的依赖都会被平铺到同一层面。这样,因为require寻找包的机制。如果A和C都依赖了B。那么A和C在自己的node_modules中未找到依赖C的时候会向上寻找,并最终在与他们同级的node_modules中找到依赖包C。
这样,就不会出现重复下载的情况。而且依赖层级嵌套也不会太深。因为没有重复的下载,所有的A和C都会寻找并依赖于同一个B包。自然也就解决了实例无法共享数据的问题
这种平铺的结构看似完美,但其实依然存在一些细节上的问题。
- 依赖结构的不确定性
- 扁平化算法的复杂度比较高,相对的比较耗时
- 项目中还是存在可以非法访问的问题
pnpm解决了这些问题
pnpm init
pnpm install express
然后你就会发现,express直接出现在了node_modules下面,他的依赖并没有和他处于同一目录下,而他本身目录下也不具备node_modules。像这样↓

因为node_modules下面的express仅仅只是一个软连接,pnpm直接抛弃了npm3/yarn原本在项目级别的扁平化结构。项目级别的node_modules下用软链接(什么是软连接?_百度知道 (baidu.com))代替。
那express的依赖又去了哪里?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8lw8L15B-1658892063251)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0326ee80083d4bf3bfc3dec4dda0144e~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp?)]
最后我们在.pnpm/[email protected]/node_modules/ 下面找到了express的依赖。
使用pnpm下载的所有依赖都会以.pnpm/依赖名@版本号/node_modules/这种形式被存储。
乍一看,好像又从扁平化管理回到嵌套结构了。性能不是倒退了吗?
不是的。
一开始从npm1和npm2的嵌套结构变成扁平化结构是为了解决
- 包被重复安装
- 依赖示例无法共享
- 依赖层级太深
这三个问题。而.pnpm/依赖名@版本号/node_modules/下面的依赖也全部都是软连接。这些软连接指向存储在store中的文件。(store是pnpm的文件公共存储空间,在后面会有介绍)

发现这种设计的巧妙之处了吗。
因为.pnpm/依赖名@版本号/node_modules/下面都是软连接,他们指向同一块存储空间。所以也就不存了包会重复安装和依赖实例无法共享的问题。
而,express所有的依赖都会在.pnpm/依赖名@版本号/node_modules/这个目录下被扁平化处理,同样解决了依赖结构太深的问题。
还有将包本身和依赖放到同一目录下,这样,利用require的特性也能够找到所有的依赖包。再将包本身的软连接放到外层的node_modules中。这样,node_modules中的包在结构上就几乎和package.json中的内容保持一致。为什么说几乎一致而不是完全一致?因为有些包有变量提升,会被提升到外层node_modules中。但是大体上还是一样的。
到这里,pnpm就又解决了npm3/yarn当时没有解决的依赖结构的不确定性。
关于npm3/yarn未解决的非法访问问题
当我们再项目中引用的时候,他会去node_modules中去寻找。由上图可知,只会在node_modules下面的第一层去寻找!!! 而pnpm的机制会让node_moduels下只有一级依赖包的软链接(也就是说如果你下载一个express,那么项目级别的node_modules下就只有express的软连接而没有express的依赖包的软链接)。所以如果你在自己的项目中直接去引用二级依赖包的话,会报错,直接找不到 (如上图) 。
可能有些同学还不理解,没关系,我们再举个例子。
我们下载了一个 A包。A包的软连接在项目级别的node_modules中,但是A包的所有依赖包都在.pnpm/依赖名@版本号/node_modules/下面。假设C包是A包的依赖包。我们直接在项目中使用require/import引用C包的话。require/import会去项目级别的node_modules中寻找。然后就会发现项目级别的node_modules下面只有一个A包的软连接,没有A包的依赖C包,找不到,就会报错。这样,只要C包没有在项目的package.json中声明,就无法访问(避免了非法访问)。
所以。到这里。pnpm也解决了npm3和yarn中非法访问的问题。
而且,非法访问的这个问题以当前的npm和yarn的版本,使用在项目级别的node_modules下进行扁平化的管理的机制,几乎无法避免。pnpm却完美的解决了。
边栏推荐
- Reflection tricks can boost your performance by N times
- 分布式系统大势所趋,银行运维如何与时俱进?
- 最远点采样 — D-FPS与F-FPS
- Flutter 环境变量配置和flutter doctor中的错误解决
- PyQt5快速开发与实战 7.4 事件处理机制入门 and 7.5 窗口数据传递
- Access to display the data
- HashSet and LinkedHashSet
- Farthest Point Sampling - D-FPS vs F-FPS
- Functional Interfaces & Lambda Expressions - Simple Application Notes
- An article to understand service governance in distributed development
猜你喜欢

回板后,处理器不启动,怎么办?

C language classic practice questions (3) - "Hanoi Tower (Hanoi)"

电路分析:运放和三极管组成的恒流源电路

虚幻引擎图文笔记:could not be compiled. Try rebuilding from source manually.问题的解决

SEER数据库中“手术变量(RX SUMM-SURG OTH REG/DIS )”下的字段解释

How to run dist file on local computer

02-课程发布

Jetpack Compose 从入门到入门(八)

用示波器揭示以太网传输机制

公共Jar包的版本管理
随机推荐
Concise Notes on Integrals - Types of Curve Integrals of the First Kind
How to Assemble a Registry
ClickHouse
C language classic practice questions (3) - "Hanoi Tower (Hanoi)"
转行软件测试,报培训班3个月出来就是高薪工作,靠谱吗?
Farthest Point Sampling - D-FPS vs F-FPS
PyQt5快速开发与实战 7.4 事件处理机制入门 and 7.5 窗口数据传递
ACL 2022 | Introduce angular margin to construct comparative learning objectives and enhance text semantic discrimination ability
Integral Topic Notes - Path Independent Conditions
Use the R language to read the csv file into a data frame, and then view the properties of each column.
20个电路能懂5个以上,足以证明你在电子行业混过!
[Fun BLDC series with zero basics] Taking GD32F30x as an example, the timer related functions are explained in detail
Excel xlsx file not supported两种解决办法【杭州多测师】【杭州多测师_王sir】
编程界的“躲猫猫”比赛 | 每日趣闻
Access to display the data
The FPGA based protocol 2: the I2C read and write E squared PROM
反射技巧让你的性能提升 N 倍
PyQt5快速开发与实战 8.1 窗口风格
回板后,处理器不启动,怎么办?
stugc_paper