文章目录
- 一、建立直觉
- 二、一个比喻
-
- [硬链接(Hard Link)](#硬链接(Hard Link))
- 软链接(Symlink)
- 三、技术层面的本质区别
- 四、命令
- [五、pnpm 相关机制](#五、pnpm 相关机制)
-
- [全局 store(核心存储)](#全局 store(核心存储))
- [node_modules 结构(关键)](#node_modules 结构(关键))
- 最终效果
- [六、为什么要"硬 + 软"一起用](#六、为什么要“硬 + 软”一起用)
- 七、现实开发中的典型场景
-
- [场景 1:pnpm / monorepo](#场景 1:pnpm / monorepo)
- [场景 2:Docker 镜像优化](#场景 2:Docker 镜像优化)
- [场景 3:本地开发调试包](#场景 3:本地开发调试包)
- [场景 4:日志 / 配置共享](#场景 4:日志 / 配置共享)
- 坑点
-
- [1. 删除源文件](#1. 删除源文件)
- [2. Git 行为](#2. Git 行为)
- [3. 跨磁盘](#3. 跨磁盘)
- 总结
一、建立直觉
- 硬链接(hard link) :多个"文件名",指向同一个文件内容(inode)
- 软链接(symbolic link / symlink) :一个"快捷方式",指向另一个路径
二、一个比喻
假设有一本书:
硬链接(Hard Link)
-
有 3 个书名:
- 《A》
- 《B》
- 《C》
-
但其实都是同一本实体书
特点:
- 改任何一本,其他"名字"看到的内容也变
- 删除一个名字,书还在
- 必须在同一个"图书馆"(文件系统)
软链接(Symlink)
- 有一本书《A》
- 另外有个"快捷卡片"写着:去 A 那里看
特点:
- 卡片只是指路,不存内容
- A 被删了 → 卡片就失效(悬空)
- 可以指向任意位置(跨目录/磁盘)
三、技术层面的本质区别
| 对比 | 硬链接 | 软链接 |
|---|---|---|
| 指向 | inode(文件内容) | 文件路径 |
| 是否占用额外空间 | 几乎不占 | 很小(存路径) |
| 删除源文件影响 | 不影响 | 链接失效 |
| 是否可跨文件系统 | 不可以 | 可以 |
| 是否可链接目录 | 一般不允许 | 可以 |
| inode 是否相同 | 相同 | 不同 |
其中可能不太能理解的是:为什么删除源文件不影响硬链接?
这是因为,在文件系统里,"文件内容"和"文件名"是两件完全不同的东西。
一个文件 ≠ 一个东西,而是两层结构:
文件名(目录项) → inode(真实数据)
举个例子,我们看到 file.txt,但系统里是:
file.txt ─────→ inode#1234 ─────→ 数据(内容)
对于硬链接来说:
bash
file.txt ──┐
├──→ inode#1234 → 数据
hard.txt ──┘
所以,删除所谓的源文件,也只是删除一个"名字",inode 还在,数据就还在。
注意,这个 inode 只有在没有任何引用它时,就会被自动回收,才算做真正被删除。
四、命令
创建硬链接
bash
ln file.txt hard.txt
创建软链接
bash
ln -s file.txt soft.txt
看区别
bash
ls -li
会看到:
- 硬链接:inode 一样
- 软链接:inode 不一样,且有箭头

五、pnpm 相关机制
我们都知道 pnpm 很省空间。其实:
pnpm 主要用的是:硬链接 + 软链接组合拳。
全局 store(核心存储)
bash
~/.pnpm-store/
这里存的是:
唯一一份真实文件
node_modules 结构(关键)
pnpm 不像 npm 那样复制依赖,而是:
第一步:硬链接
把 store 里的包:
bash
store/react@18 → node_modules/.pnpm/react@18
用的是 硬链接
所以:
- 不复制文件
- 直接复用磁盘数据
第二步:软链接(依赖关系)
再通过 symlink 构建依赖树:
bash
node_modules/react → .pnpm/react@18/node_modules/react
用的是 软链接
最终效果
bash
node_modules/
react → symlink
.pnpm/
react@18/
node_modules/
react (hard link 到 store)
六、为什么要"硬 + 软"一起用
这是个非常精妙的设计。
如果只用硬链接
问题:
- 无法表达依赖关系
- node_modules 树结构不好维护
如果只用软链接
问题:
- 每个文件仍然要存在一份真实数据
- 不能节省空间
pnpm 的组合优势
| 目标 | 技术 |
|---|---|
| 节省磁盘 | 硬链接 |
| 构建依赖树 | 软链接 |
七、现实开发中的典型场景
场景 1:pnpm / monorepo
- 节省磁盘
- 快速安装
- 多项目共享依赖
场景 2:Docker 镜像优化
- 多层复用文件
- 减少镜像体积
(底层也类似 inode 复用思想)
场景 3:本地开发调试包
bash
npm link
pnpm link
本质就是:
- 用 软链接把本地包接入项目
场景 4:日志 / 配置共享
bash
ln -s /var/log/app.log ./log
常见于:
- 多服务共享文件
- 快速访问
坑点
1. 删除源文件
bash
rm original
- 硬链接:还在
- 软链接:坏掉
2. Git 行为
- Git 不跟踪硬链接关系
- Git 会记录软链接(路径)
3. 跨磁盘
- 硬链接:失败
- 软链接:正常
总结
硬链接 = 共享"内容",软链接 = 共享"路径"。
而 pnpm 的本质是:
用硬链接解决"存储问题",用软链接解决"结构问题"。