Bun v1.3.14 引入了全局虚拟存储(global virtual store),
通过硬链接复用缓存、软链接构建隔离的依赖树,
在依赖管理和磁盘效率上正向 pnpm 看齐,两者越来越像了。
1. 软/硬链接的 JS 直觉
可以用 JS 对象引用,快速理解软硬链接。
硬链接:多个引用指向同一个对象。
删除其中一个引用,原对象不会销毁。
所有引用删除后,对象才会被回收。
bash
const obj = { data: "Hello" };
const hard = obj;
delete obj;
console.log(hard.data); // "Hello"
软链接:只存储目标路径,动态查找资源。
一旦原文件/对象删除,软链接就会失效悬空。
bash
const reg = { target: { data: "Hello" } };
const soft = () => reg.target;
delete reg.target;
console.log(soft()?.data); // undefined
总结:硬链接共享实体;软链接仅存路径。
2. Bun 和 pnpm:并非一硬一软
Bun 和 pnpm 底层同时支持硬链接、软链接。
二者无本质技术差异,只是默认策略不同。
pnpm:硬链接存真实文件,软链接构建依赖树。
天然依赖隔离,默认杜绝幽灵依赖。
Bun v1.3.14+(单项目):默认扁平 Hoisted 结构。
不使用软链接树,行为接近 npm / yarn。
新版支持全局虚拟存储,大幅节省磁盘。
核心区别:pnpm 默认软链接树,Bun 默认不用。
3. 什么是软链接树(核心概念)
软链接树是隔离式的 node_modules 目录结构。
真实包文件统一存放在虚拟存储目录。
项目目录依靠多层软链接,映射真实文件。
它可以严格隔离依赖层级,杜绝幽灵依赖。
Hoisted 扁平模式无软链接树,依赖全部平铺。
扁平模式兼容性好,但存在隐式依赖风险。
4. Bun 软硬链接代码示例
bash
import { link, symlink, unlink, readFile, writeFile } from 'node:fs/promises';
await writeFile('orig.txt', 'Bun');
await link('orig.txt', 'hard.txt'); // 硬链接
await symlink('orig.txt', 'soft.txt'); // 软链接
await unlink('orig.txt');
console.log(await readFile('hard.txt', 'utf8'));
// soft.txt 读取报错 ENOENT
运行命令:bun run demo.ts
5. 幽灵引用
幽灵引用分为依赖、文件系统两层场景。
依赖层面:代码使用未声明的包。
因依赖提升本地可运行,线上极易报错。
文件系统层面:源文件删除,软链接残留。
访问悬空软链接,会抛出 ENOENT 错误。
6. 幽灵引用与 Bun 的关系
幽灵引用不是 Bun 造成的。
根源是项目编码、依赖管理不规范。
比如漏写依赖、依赖隐式提升、写死绝对路径。
Bun 只是更快暴露了这些不规范问题。
规范声明依赖,任意包管理器都无幽灵依赖。
7. bun i 链接器参数(--linker hoisted / --linker isolated)对比 + v1.3.14 新特性
Bun v1.3.14 新增全局虚拟存储。
多项目共享缓存,磁盘效率对齐 pnpm。
通过 --linker 可切换两种依赖布局策略。
| 参数 | -linker hoisted | -linker isolated | | :-- | :-- | :-- | | 依赖结构 | 扁平 node_modules | 严格隔离 node_modules | | 软链接树 | ❌ 不使用 | ✅ 启用隔离软链接树 | | 幽灵依赖 | ✅ 允许 | ❌ 严格禁止 | | 磁盘占用 | 极低(全局共享) | 极低(全局共享) | | 安装速度 | 极快 | 极快(差距<5%) | | 兼容性 | 兼容所有老旧项目 | 部分老包需要适配 |
hoisted(单项目默认)适用场景
-
• npm / yarn 老项目迁移
-
• 存在隐式依赖,暂时无法重构
-
• 需要传统扁平 node_modules 结构
isolated(Monorepo 默认)适用场景
-
• 全新项目,从零杜绝幽灵依赖
-
• Monorepo 多子包严格隔离
-
• CI 环境保障依赖声明完整
-
• 想用 Bun 性能 + pnpm 隔离能力
小结:兼容旧项目用 hoisted;严谨规范用 isolated。
8. Bun(v1.3.14+) 与 pnpm 完整对比
| 对比维度 | pnpm | Bun(v1.3.14+) | | :-- | :-- | :-- | | 底层能力 | 硬链接 + 软链接 | 硬链接 + 软链接(macOS 克隆优化) | | 缓存机制 | 全局 Store 共享 | 全局虚拟存储,对齐 pnpm | | 单项目结构 | 隔离软链接树 | 扁平 Hoisted | | Monorepo 结构 | 严格隔离 | 严格隔离(isolated) | | 防幽灵依赖 | ✅ 默认支持 | isolated 支持,hoisted 不支持 | | 磁盘效率 | 极高 | 极高(新版持平 pnpm) | | 安装速度 | 较快(10-15s) | 极快(3-5s,快 2-4 倍) | | 速度差异 | 无 | 两种模式差距<5% | | Monorepo 成熟度 | 行业标杆 | 快速迭代,基础完善 | | 生态兼容 | 稳定 100% 兼容 | 近 100%,原生模块需测试 | | 核心优势 | 稳定、隔离、省空间 | 极速、工具链一体化、新版省空间 |
选型建议
追求稳定、严格隔离、磁盘极致节省 → 选 pnpm。
追求极速开发、新版存储优化 → 选 Bun。