1.硬链接和软链接
- 硬链接(
hard Link
)硬链接
是一个电脑系统中多个文件平等共享的使用一个存储单元
删除一个文件
,其他文件可以继续使用
- 软链接(
soft Link
或者符号链接symbol Link
)- 其包含有一条以绝对路径或者相对路径 的形式指向其它文件 或者目录 的
引用
(其实就是快捷方式) 当删除了源文件
软连接 的文件就无法使用
- 其包含有一条以绝对路径或者相对路径 的形式指向其它文件 或者目录 的

注意:硬链接可不是复制文件,可以参考下面这张图
2.使用硬链接和软链接与拷贝的区别
-
文件的拷贝
:文件的拷贝每个人都非常熟悉,会在硬盘中复制出来一份新的文件数据;- window :
copy foo.js foo_copy.js
- Macos :
cp foo.js foo_copy.js
- window :
-
文件的硬链接
:- window :
mklink /H aaa_hard.js aaa.js
- Macos :
ln foo.js foo_hard.js
- window :
-
文件的软连接
- window :
mklink aaa_soft.js aaa.jss
- Macos :
ln -s foo.js foo_copy.js
- window :

3.pnpm到底做了什么呢?
-
当使用
npm
或yarn
时,如果你有100 个依赖,并且所有依赖都有一个相同的依赖包,那么,你在硬盘上就需要保存100 份该相同依赖包的副本 -
如果是使用
pnpm
,依赖包将被存放在一个统一的位置 -
如果你对同一依赖包使用相同的版本 ,那么磁盘上只有这个依赖包的一份文件
-
如果你对同一依赖包需要使用不同的版本 ,则仅有版本之间不同的文件会被存储起来
-
所有文件都保存在硬盘上的统一的位置:
-
当安装软件包时,其包含的所有文件都会硬链接到此位置,而不会占用额外的硬盘空间
-
这让你可以在项目之间方便地共享相同版本的依赖包
-
解释下面图片
npm/yarn的痛点
:每个项目独立存储依赖文件,导致重复占用磁盘空间(如中间图彩色矩形重复堆叠);pnpm的突破
:用全局硬链接保存单一依赖副本 ,项目通过符号链接引用(图最右侧中心节点向外发散连接),避免重复存储。

4.pnpm
/npm
/yarn
对比的直观差异
工具 | 依赖存储方式 | 安装速度 | 磁盘占用 | 依赖隔离性 |
---|---|---|---|---|
npm |
本地缓存复制+扁平化结构 | 慢 | 高 | 中(可能幻影依赖) |
yarn |
扁平化结构 yarn.1.x 采用的是本地缓存复制 yarn.2.x 采用的全局缓存复用 |
较快 | 中 | 中(可能幻影依赖) |
pnpm |
全局硬链接+项目符号链接 | 最快 | 最低 | 强(严格隔离) |
- 本地缓存复制: 每个依赖都存储一份,浪费空间
- 全局缓存复用 :缓存单独放在一个地方,要用直接拿来用,节省空间
pnpm 也差不多,用链接指向全局仓库
5.幻影依赖是什么?
- 如图:我的依赖项目
devDependencies
只有一个依赖vite
, 因为npm5.x
k开始安装的依赖都是扁平化的vite
这个插件又依赖其他插件,所以看到除了vite这个打包工具还有很多其它插件在外面

- 现在
index.js
去使用**非自己安装的依赖nanoid
**这个插件,我并没有下载nanoid
这个插件 但是还是使用成功- 这就是幻影依赖 ,我并没有下载这个依赖,只是因为
vite
这个打包工具在依赖他,因为扁平化原因我也能使用 - 这是一个不规范的问题 ,如果我在项目中使用了幻影依赖 ,并没有去下载,如果我们后面更新
vite
,vite
后面不依赖这个插件,node_modules
就会删除这个插件,此时我们项目就会报错
- 这就是幻影依赖 ,我并没有下载这个依赖,只是因为
js
import { nanoid } from 'nanoid';
console.log('nanoid', nanoid()); // nanoid etubJqBXElEm5uw_xaQKk
5.1pnpm
是怎么解决的?
-
pnpm
采用则是非扁平化 的node_modules目录
- 当我们使用
pnpm
安装自己的依赖在node_modules
第一层都是软链接,这样避免了幻影依赖 - 不是我们安装的依赖是不会出现在第一层的 ,硬链接的依赖 都是放在
.pnpm
这个文件中 - 插件依赖另一个插件,另一个插件的依赖项软链接 会放在这个插件的
node_modules
中 - 如图所示:软链接最右边都有一个小箭头
- 当我们使用
-
如 第一张图 所示:打开
node_modules
首先我们看到vite
快捷方式(软连接) 和.pnpm
于.bin
三个文件目录vite
软链接指向.pnpm
文件夹下存在真实的[email protected]
就是硬链接指向.pnpm store
- 在
vite
的node_modules
中又依赖其他几个包,其他几个依赖包也是软链接 指向.pnpm
文件目录的硬链接的依赖包
-
第二章官方图 所示:
node_modules
下我们就安装了bar
插件-
bar软链接
指向.pnpm
文件目录中的[email protected]
这个硬链接
,这个硬链接指向.pnpm store
-
但是
[email protected]
插件又依赖foo
这个插件,这个foo
也是一个软链接
-
foo
软链接 又指向.pnpm
文件目录中的foo
@1.0.0硬链接
,这个硬链接指向.pnpm store
-
.pnpm store
也是一个硬链接 此时他指向的就是磁盘中的真实数据
-
5.2 pnpm
的基本使用
npm 命令 |
pnpm 等价命令 |
|
---|---|---|
npm install |
pnpm install |
|
npm install |
pnpm add |
|
npm uninstall |
pnpm remove |
|
npm run |
pnpm |
5.3 pnpm store
存储位置
- 在
pnpm
7 及更早版本中,存储可能始终位于用户主目录下,如C:\Users\username\AppData\Local\pnpm\store
- 在
pnpm
7之后.pnpm store
位置发生了变化- 假如我的项目在
F盘
下 我安装依赖pnpm install
此时 F盘根目录会创建.pnpm-store
,所有F盘
用pnpm install
安装的依赖最终都会指向这里
- 假如我的项目在
- 为什么要更换位置?
- 统一位置可能导致跨磁盘复制依赖,增加磁盘空间占用和降低安装速度。
- 除了效率,还有文件系统限制、用户体验改进和多磁盘环境的适配需求。
版本 | 默认存储位置 | 多磁盘支持 | 性能优化 |
---|---|---|---|
pnpm 7 及更早 |
用户主目录(如 C:\Users\username\AppData\Local\pnpm\store ) |
需要手动配置,自动创建可能不明确 | 可能跨磁盘复制,效率较低 |
pnpm 8 及之后 |
每个磁盘根目录(如 F: .pnpm-store ) |
自动创建,明确支持多磁盘存储 | 确保同一磁盘硬链接,效率更高 |
-
可以通过命令查看位置 :获取当前活跃的store目录
pnpm store path
-
清理当前活跃store 目录里面当前未被引用的包来释放store的空间
pnpm store prune
更多命令和用法可以参考pnpm的官网:pnpm.io/zh/