在谈起pnpm时先来聊一聊之前的npm和yarn有什么存在的问题
在npm3之前我们安装依赖的目录是这样:
node_modules
├────packageA
├────node_modules
│ ├────packageB
│ ├────node_modules
│ ├────packageC
│ ├────node_modules
只要安装依赖下赖依赖于其他依 就会套一层node_modules 如果当前层级还有其他依赖呢?思路也很简单,我再给你套一层node_modules,以此类推
这样做会有什么问题呢?
这个方法是yarn先提出来的,npm3紧随其后
解决思路: node_modules扁平化
node_modules
├────packageA
├────packageB
├────packageC
这样我们安装的依赖呢 就解决了上面两个问题,如果当前依赖下依赖其他依赖,直接提升到根目录的node_modules下,这样及可以解决路径长度问题又解决了资源不共享问题。
但是呢,同样就会出现新问题
pnpm代表什么?pnpm代表 performant(高性能的)npm
那pnpm到底解没解决上面的问题呢?为了测试 分别使用npm 和 pnpm 下载axios包
npm i axios
// and
pnpm i axios
从下载来看呢 目前可以解决 幽灵依赖问题 也就是说pnpm并没有使用扁平化的方式,那么pnpm 下载下来的会不会嵌套很多层级呢?
注意看axios文件上有一个小箭头,返回看你的桌面上是不是所有的软件上都带上一个箭头呢?他呢其实就是软链接本质上就是快捷方式,而且在包上面还有一个.pnpm的文件,存在即合理,必然有他的用处,当前看到的axios就是通过.pnpm目录下axios进行软链接,然后再通过.pnpm下的axios和磁盘目录下的.pnpm-store进行建立硬链接。
当然听起来比较抽象,接下来解释下什么是硬链接/软链接。
基维百科:硬链接(英语:hard link)是计算机文件系统中的多个文件平等地共享同一个文件存储单元(如MFT条目、inode)
如何建立硬链接?
新建出一个文本文件 随意写上文字 例如a.text 准备为a建立硬链接
以windows为例执行cmd命令
E:\项目\test\硬链接>mklink /h b.txt a.txt
这时候同级目录下就会产生一个b.txt 打开正是a.txt的文字内容,这时候不管你修改a还是b他们都会进行互相修改,原因就是使用了硬链接修改了同一个磁盘的地址。可以理解成js的赋值对象
let a = {}
let b = a
基维百科:软链接(符号链接、Symbolic link)是一类特殊的文件, 其包含有一条以绝对路径或者相对路径的形式指向其它文件或者目录的引用。
同理新建a文本文件
E:\项目\test\软链接>mklink b.txt a.txt
打开b.txt 就会 打开的a.txt文本,通过路径引用到a.txt
接下来再看pnpm的目录流程
每次硬链接都是从 .pnpm store 进行链接,pnpm有什么好处呢?
.pnpm store存在哪里呢?
在pnpm i 的时候就已经告诉你了,默认情况下是在磁盘根目录下的.pnpm-store
为什么不是在其他磁盘?
原因是硬链接只能在当前磁盘上进行链接,不能跨磁盘访问。
注意在倒数第二行 downLoad是 0 ,也就是没有进行下载,直接从.pnpm-store 进行硬链接起来。
如果包存储在全局存储中,为什么我的 node_modules 使用了磁盘空间?
官网回答:pnpm 创建从全局存储到项目下 node_modules 文件夹的 硬链接。 硬链接指向磁盘上原始文件所在的同一位置。 例如,如果您的项目有 foo 作为依赖者 并且它占用了 1MB 的空间。 然后看起来它将占用了 项目的 node_modules 文件夹和全局的 存储空间相同的空间。 但是,该 1MB 是磁盘上两个不同位置的相同空间 。 所以 foo 总共占用 1MB,而不是 2MB。 大白话也就是值只占用了同一个空间。
pnpm的缺点:
如果想彻底删除一个不再使用的包,可以使用pnpm的剪裁
pnpm store prune
和npm对比命令
npm 命令 | pnpm等效 |
---|---|
npm install |
pnpm install |
npm i |
[pnpm add ] |
npm run |
[pnpm ] |