包管理器 pnpm 中的软链与硬链
平时都是使用 npm
和 yarn
来作为前端项目的包管理,最近突然听到别人说 pnpm
比较流行,其中的软链和硬链设计很秀。
本文就是记录下自己查看 pnpm
中包管理中软链和硬链的设计。
首先大家可以先自行了解下什么事软链和硬链。参考一下这篇文章
安装
然后开始安装 pnpm
,具体安装方法可以看它的官网。网址在这里
创建项目
好了,然后我们就创建一个项目
cd ~/Documents
mkdir pnpm-demo
cd pnpm-demo
pnpm init
当然你会发现 pnpm init
实际和 npm init
,没有什么区别,那这就对了, pnpm
主要是用来管理npm
包的,实际的名利和 npm
差距不大。
安装一个包
来来来,这回我们要用 pnpm
安装一个包了~~~ 就 vue
吧
pnpm install vue
看是不是和 npm
一样的命令。
安装成功之后我们查看一下项目中的 node_modules
目录。
我用的是vscode编辑器,大家注意到 vue
文件后面是不是有个回车的icon,这个代表当前这个文件是一个软连接文件。
可以通过命令查看一下,可以看到 node_modules/vue
实际是 .pnpm/vue@2.6.14/node_modules/vue
的软连接
我们再看下 .pnpm/vue@2.6.14/node_modules/vue
中的内容,就是 vue
的包。
也就是说当你的项目中使用了 import Vue from 'vue'
的时候,根据 node
的路径分析规则,他会去 node_modules/vue
中查找,而 node_modules/vue
实际是 .pnpm/vue@2.6.14/node_modules/vue
的软连接
好,这时候你可能会有疑问:
-
为什么不是
.pnpm/vue@2.6.14
来存放vue
,然后软链到.pnpm/vue@2.6.14
,反而要用.pnpm/<packagename>@<version>/node_modules/<packagename>
的形式 -
如果
vue
有其他以来怎么办
补充个小Tip
软链接的特性决定了在执行过程中他的文件路径和软连接地址是不配匹配的
举个例子
// <root>/script/index.js
console.log(process.cwd());
console.log(__dirname);
console.log(__filename);
# 创建上述文件的一个软件链接
ln -s script/index.js index-ls.js
# 执行软链接文件
nodre index-ls.js
# 返回结果
$ <root>
$ <root>/script
$ <root>/script/index.js
## 真正执行的实际上是 index.js
回到正文
那我们接着安装一个 react
吧,反正现在前端项目不是 react
就是 vue
。
pnpm install react
安装完可以看到 node_modules
下面多了 react
,但是 .pnpm
里面却多了好多包。
再看下 .pnpm/react@17.0.2
下面就知道, pnpm为什么会这么设计了。
以 react 举例 .pnpm/react@17.0.2/node_modules/
下面除了有react自己,还有react依赖的npm包。
这样的结合软链、包查找规则以及防止文件路径过长来设计的
还是要举例说明下
- 项目中引用了
react
,依赖管理的规则会去node_modules
里面查找react
- 当找到
reat
之后,在代码执行过程中又发现react
依赖了object-assign
- 依赖管理的规则会查找当前目录下的
node_modules
,如果没有找到会查找父目录的node_modules
一直找到根目录为止 node_modules/react
实际是.pnpm/react@17.0.2/node_modules/react
的软链,它下面是没有node_modules
的,那么根据规则,他会一直往上查找,直到找到.pnpm/react@17.0.2
下的node_moduels
中有object-assign
- 如果
object-assign
也会按照上面的流程执行
这就是 pnpm 如何根据软链特性以及依赖查找的规则实现一个巧妙的设计,npm包路径的长度最长也就是.pnpm/<packagename>@<version>/node_modules/<packagename>
可能说的比较饶,大家可以自行操作一下
pnpm 的硬链
上面可以看到 pnpm 使用软链达到一个巧妙的实际
在 pnpm 中还使用了硬链来实现快速的安装
我们查看下 node_modules/.pnpm/vue@2.6.14/node_modules/vue/package.json
这个文件
可以详细的看到这个文件的信息
索引节点 inode 为 st_ino=18046034
硬链 st_nlink=3
也就是文件索引的对应着系统上 3个地址,了解过上面说的硬链与软链就应该知道是什么意思。
find ~ -inum 18046034
# /Users/xxxxx/.pnpm-store/v3/files/b2/2c30605a327a1c3cdc0003e8b0d1d136ebf92bad4c3a7997c3849041cebfd75514cf18f459a77968b366b1d3e2353de6b52326cfde7955e1c7e9ff7b9996c3
上面的命令可以查找文件地址对应的文件inode
为 18046034
如果你再新建个项目,再次安装 vue@2.6.14
然后重新查看node_modules/.pnpm/vue@2.6.14/node_modules/vue/package.json
你会返现 st_nlink=4
这说明如果你安装过一次之后,以后每次安装都会硬链一个到你的项目中,这比你原先缓存的复制的方式块多了。但有个缺点就是修改都是同步的,也就是说你修改当前项目中的node_modules会影响其他项目。
转载自:https://juejin.cn/post/7044807973868142622