
最近打开技术社区热门话题里几乎一半都绕不开同一个词依赖。Vue 项目装依赖时版本对不上Maven 下载依赖时中央仓库地址超时Linux 上装个 Oracle 驱动提示缺 libaio1Flutter 各个版本依赖包拉不下来甚至连 ChatGPT 客户端安装都会卡在“正在检查依赖项”。你会发现一个很残酷的事实不管你用哪门语言、哪套工具链“依赖”永远是开发体验里最折磨人的一环。Bun 1.4 这次的更新正是冲着这个痛点来的。标题里那句“秒删15个依赖”虽然带着夸张成分但背后确实藏着一个非常重要的变化JavaScript 生态的依赖管理正在从“人工声明、手动治理”走向“源码分析、自动清理”。这不是某个包管理器加了几个命令那么简单而是工具链开始理解你的代码到底依赖了什么。这篇文章不打算逐条念 release notes。我会把重点放在三件事上第一Bun 1.4 的依赖清理能力到底解决了什么真实问题第二如何在自己的项目里跑通这套依赖治理流程第三从工程角度看Bun 现在究竟能不能替代你现有的 Node.js 工具链。1. 这篇文章真正要解决的问题1.1 所有人都在和依赖死磕先看一组非常普遍的日常场景。前端同学用 Vue 或 React 初始化项目第一件事是安装依赖。运气好的时候npm install一次通过运气不好就要面对 ERESOLVE 错误、peerDependencies 冲突、幽灵依赖问题。后端同学用 Maven 或 Gradle也要经历同样的痛苦依赖从哪个仓库下载、版本号冲突怎么排除、循环依赖怎么解。运维同学更惨Docker 镜像里缺一个 native 依赖整个服务就启动不了。这些场景看似互不相干但本质是同一个问题依赖被安装得太容易被清理得太难。在 JavaScript 生态里这个问题被放大到了极致。新建一个项目哪怕只写几行代码node_modules都可能膨胀到几百 MB。很多依赖在package.json里躺了好几年代码里早就没有使用了却依然每次安装都带着全家桶一起进来。1.2 Bun 1.4 真正改变了什么Bun 1.4 最有价值的点不是又提升了多少安装速度而是引入了对项目源码的分析能力。当执行安装命令时它能识别出哪些依赖已经被声明但实际没有被业务代码引用并自动进行处理。从官方演示和社区反馈来看一个中等规模项目里扫出十几个没用到的依赖并不算夸张。这也是“秒删15个依赖”这个说法的来源。关键区别在这里传统包管理器只管理“你声明了什么”。Bun 1.4 开始关注“你的代码真正用到了什么”。1.3 这篇文章适合谁读下面三类读者建议收藏这篇文章慢慢看。第一类是日常被 npm 和 pnpm 依赖问题折磨的前端/全栈开发者。你不需要立刻把项目迁移到 Bun但需要知道一个更高效的依赖治理思路长什么样。第二类是做 Node.js 服务端开发的技术负责人。你在做技术选型时最关心的不是“快”而是“能不能减少维护成本”。Bun 1.4 的依赖清理能力实际上是在帮你控制项目的技术债。第三类是正在研究容器化部署的运维和 SRE 工程师。Bun 的安装速度快、产物静态化程度高在 Docker 环境里做依赖安装时优势非常明显。2. Bun 是什么为什么不是又一个运行时2.1 一个工具替代四个工具在正式开始之前先给没接触过 Bun 的读者补个背景。Bun 是一个 JavaScript/TypeScript 全能工具链它把四个原本需要单独安装的工具集成了进来Bun 提供的能力原本对应的工具解决的问题JavaScript 运行时Node.js直接执行 JS/TS 代码包管理器npm / yarn / pnpm安装、删除、更新依赖打包器Webpack / esbuild / Rollup构建前端或服务端代码测试运行器Jest / Mocha / Vitest运行单元测试和集成测试这意味着如果你的项目愿意只需要安装一个 Bun从开发到构建到测试的整条链路都可以接管。这有点像 Rust 生态里的 Cargo一个命令搞定依赖、构建、测试和发布。2.2 底层技术选型决定了体验上限Bun 之所以能在速度和内存占用上做出差异化核心原因是两个技术决策。第一个是使用 JavaScriptCore 引擎而不是 V8。JavaScriptCore 是 Safari 浏览器和 WebKit 系应用的底层引擎在启动速度上比 V8 有天然优势。第二个是使用 Zig 语言编写核心代码。Zig 是一门偏底层的系统编程语言没有 GC垃圾回收内存控制非常精确。对工具链这种对延迟敏感的程序来说这个选择能带来实打实的性能收益。这些技术选型反映在产品上就是写代码时几乎感觉不到工具本身的启动延迟。bun run一条命令执行下来体感上比npm run快很多。2.3 Bun 1.4 的功能重心Bun 1.4 这次的更新重点集中在“工程化体验”上。从社区讨论和标题透出的信息看依赖清理是最大的亮点同时兼容性适配、使用体验细节也有不少改进。值得注意的是Bun 的版本迭代速度非常快。如果你两年前试用过 Bun发现它连某些框架都没适配好那现在的 Bun 1.4 已经基本不是同一款产品了。很多早期硬伤都已经被修复现阶段选择 Bun 已经不是“尝鲜”而是“降本”。3. “秒删15个依赖”背后的依赖治理逻辑3.1 没有工具辅助时清理依赖有多痛苦很多人以为清理依赖很轻松打开 package.json把不用的包删掉然后重新安装。但真实项目尤其是有一定历史的项目问题会变得非常复杂第一你不知道哪个包真正被用了。项目里可能有几十个文件依赖关系经过几轮重构后很多 import 语句已经被删除或者替换但 package.json 里的声明还留着。第二你不知道哪个包间接提供了能力。A 依赖 BB 依赖 C。你在代码里直接 import 了 C但 package.json 里并没有 C。删除 C 会导致崩溃删除 B 同样会牵连 C。第三你不敢轻易动手。生产和 CI 环境都用同一个 lockfile 安装依赖一旦误删线上事故就是少则一小时的排查成本。所以大部分项目里的依赖清理都只能靠人工抽时间做。就像整理家里杂物间总说哪天有空了大扫除结果永远等不到那天。3.2 Bun 的依赖清理是怎么工作的Bun 1.4 的做法是安装依赖时不仅读取 package.json还会分析项目源码结构。它会梳理出所有 import 和 require 语句建立一个“源码引用地图”。然后对比 package.json 里声明的依赖找出哪些包从未出现在引用地图里。这些从未被引用的纯声明依赖就会被清理掉。这个机制本质上和 ESLint 未使用变量检查很像只是把检查目标从代码变量换成了外部依赖包。因为它基于静态分析所以不依赖运行时环境也不会真的执行你的业务代码。3.3 为什么这是开发体验的分水岭以往依赖管理工具和服务器的关系是你告诉我装什么我就装什么。Bun 1.4 把这件事变成了我会自己看你的代码并提醒你你其实不需要这么多东西。这个转变的意义不亚于穿在 lint 和 formatter 进入工程化流程那些原本靠自觉维护的规则变成了工具链默认执行的检查。依赖清理一旦成为安装流程的一部分node_modules 体积、lockfile 变更、CI 安装耗时、镜像构建时间都会随之下降。这套机制的价值已经超出了“省几个 G 硬盘空间”而是直接关系到研发效率和项目健康度。4. 环境准备与安装4.1 安装 BunBun 覆盖主流操作系统macOS、Linux、Windows 都能装。下面给出不同平台的安装方式。macOS 或 Linuxcurl -fsSL https://bun.sh/install | bashWindows 使用 PowerShellpowershell -c irm bun.sh/install.ps1 | iex安装完成后需要将 Bun 的安装目录加入 PATH。安装脚本一般会在 shell 配置文件中自动配置重启终端即可生效。4.2 验证安装bun --version如果输出类似1.4.x的版本号说明安装成功。还可以查看核心命令的帮助信息bun helpBun 的命令设计比较统一bun install、bun run、bun test、bun build基本不需要重新学习很多新概念。即使你之前一直在用 npm切换成本也不会太夸张。4.3 版本说明不同操作系统和不同发行版下Bun 的可用性会有细微差异。如果你的项目依赖了特定原生模块建议先在测试环境验证再决定是否全量切换。本文后面所有示例都基于 Bun 1.4 版本。老版本可能不支持依赖清理能力建议先升级到最新版本。5. 从零搭建 Bun 项目复现“秒删依赖”5.1 初始化项目首先在一个空目录里初始化一个 TypeScript 项目mkdir bun14-demo cd bun14-demo bun initbun init会生成一个最小的项目骨架。整个过程交互式操作很少会自动生成package.json、index.ts、tsconfig.json等基础文件。生成的 package.json 大致长这样{ name: bun14-demo, module: index.ts, type: module, scripts: { dev: bun --watch index.ts, build: bun build ./index.ts --outdir ./dist }, devDependencies: { types/bun: ^1.1.0 } }这里的module字段是 Bun 的入口约定。bun --watch index.ts表示文件变更后自动重启。5.2 安装几个故意不用的依赖接下来安装两个生产环境依赖但故意不在代码里使用它们bun add lodash bun add chalklodash 是工具函数库chalk 是终端着色库。在很多项目里这类工具函数库经常出现“装了很久但某次重构后彻底不用”的情况。再安装一个开发依赖bun add -d types/lodash此时 package.json 里已经声明了三个包。5.3 编写源码只引用其中一个包修改index.ts只使用 chalk// 文件路径index.ts import chalk from chalk; console.log(chalk.green(Bun 1.4 依赖清理演示)); console.log(当前项目声明了 lodash但代码中并未引用);这时候 package.json 里声明了 lodash但源码里没有任何 import 语句指向它。这正是 Bun 依赖清理要处理的典型场景。5.4 运行依赖清理执行命令让 Bun 检查项目源码并清理无效依赖bun install在 Bun 1.4 环境下安装完成后会分析源码引用情况并提示哪些依赖没有实际使用。根据提示操作后package.json 会被自动更新lodash 和 types/lodash 会从依赖列表中被移除。5.5 验证清理结果先检查 package.jsoncat package.json可以看到 lodash 相关的依赖声明已经被自动删除。再查看依赖树bun pm ls这个命令会输出当前项目实际安装的顶层依赖。如果依赖清理成功lodash 和 types/lodash 不会出现在列表里。最后对比 node_modules 的体积变化du -sh node_modules清理前lodash 会占掉十几 MB 甚至更多空间。清理后体积会明显下降。这就是“秒删15个依赖”在实际项目中的效果。真实项目里十几二十个依赖被一次清理掉体积和安装耗时的改善是非常直观的。6. 完整示例Bun 运行时、打包和测试能力依赖清理是 Bun 1.4 的亮点之一但它不是全部。下面用一个完整示例快速演示 Bun 在运行时、打包和测试方面的基本用法。6.1 一个带依赖引用的 HTTP 服务写一个最简单的 HTTP 服务// 文件路径server.ts const server Bun.serve({ port: 3000, fetch(request) { const url new URL(request.url); if (url.pathname /) { return Response.json({ message: Bun 1.4 server is running, time: new Date().toISOString(), }); } return new Response(Not Found, { status: 404 }); }, }); console.log(Server listening on http://localhost:${server.port});执行服务bun run server.ts访问http://localhost:3000接口会返回一条 JSON 消息。这个示例说明Bun 作为一个完整运行时自带 Web 标准 API。你不需要安装 express 或 koa就能写一个常见的 JSON API。6.2 用内置打包器构建前端代码Bun 内置的打包器使用起来非常简单。假设目录下有一个前端入口文件// 文件路径client.ts import chalk from chalk; const app document.getElementById(app); if (app) { app.textContent chalk.green(Frontend bundled by Bun); }执行构建命令bun build ./client.ts --outdir ./dist --minifyBun 会自动解析 TypeScript、处理依赖引入并输出压缩后的 JS 文件。整个构建过程不需要额外配置 Webpack 或 esbuild。6.3 用内置测试运行器写单元测试创建一个测试文件// 文件路径math.test.ts import { describe, expect, test } from bun:test; function add(a: number, b: number) { return a b; } describe(add function, () { test(adds two numbers, () { expect(add(1, 2)).toBe(3); }); test(handles negative numbers, () { expect(add(-1, -2)).toBe(-3); }); });执行测试bun test输出会以列表形式展示每个测试用例的运行结果。Bun 的测试运行器天然支持 TypeScript不需要额外的 Babel 或 ts-jest这是它相比 Jest 的一个重要优势。7. Bun 1.4 与 npm、pnpm、Yarn 的对比与迁移建议7.1 横向对比对比项Bun 1.4npmpnpmYarn依赖安装速度快中等较快中等磁盘空间利用一般但自动清理有效差重复安装多好全局共享内容寻址存储一般源码级依赖分析支持不支持不支持不支持运行时功能完整运行时无无无测试运行器内置需单独安装需单独安装需单独安装对 Node 兼容性大多数场景兼容原生兼容原生兼容原生兼容npm、pnpm、Yarn 的定位都是“包管理器”做的是安装依赖这件事。Bun 的定位则是“全套工具链”包管理只是其中一个模块而且它额外提供了源码依赖分析能力。这是本质区别。7.2 迁移时容易踩坑的地方从 Node.js 迁移到 Bun最容易出问题的是原生模块。如果项目依赖了 node-gyp 编译出来的原生模块使用这些需要特定编译环境的包时Bun 不一定能直接兼容。比较稳妥的做法是先在一个小项目里跑通 Bun 的安装、测试、构建流程再逐步扩展到核心项目。7.3 什么项目不建议立刻迁移下面情况建议暂缓项目重度依赖冷门的 Node.js 原生模块依赖了较多 CSPContent Security Policy相关或 Electron 供应链特殊要求的工具团队没有意愿改变现有工作流。Bun 的定位不是让所有人明天就把 Node.js 删掉而是提供一个新的选择。先把依赖清理能力用起来已经能让项目受益很大。8. 常见问题与排查思路依赖管理本身就是一个充满不确定性的领域。下面整理几个遇到概率较高的问题。问题现象可能原因排查方式解决方案bun install 后提示找不到某个模块依赖被自动清理误判查看源码中是否动态引用该依赖在代码中改为静态 import或恢复依赖声明并在文档中说明用途自动清理后运行时某个功能报错部分依赖只在运行时被 require 或由 postinstall 脚本引用检查报错栈和上线前 git diff保留必要依赖并确认该依赖确实在当前页面或功能中被直接使用从 npm 迁移后 lockfile 变化巨大Bun 使用 bun.lock 记录依赖结构查看 git diff 对比内容提交 bun.lock让团队统一使用 Bun 安装依赖Windows 下某些原生模块无法运行原生模块与 Bun 的兼容性不足查看错误堆栈和构建日志在 WSL 或 Docker 中运行或继续使用 Node.js依赖清理后package.json 变更过多项目历史包袱重很多废弃依赖积压仔细 review 变更内容分批清理一次处理少量项目不要边改边发版重点提示依赖自动清理对常规项目很安全但不要跳过代码评审。删除依赖前至少在测试环境里跑一遍核心流程。9. 工程实践与团队落地建议9.1 把依赖清理接入 CI依赖清理最好进入自动化流程。可以在 CI 里增加一个检查任务bun install --frozen-lockfile bun pm ls--frozen-lockfile会锁定依赖版本避免因为 lockfile 不一致导致 CI 和本地安装结果不同。在 CI 中跑一遍 Bun 的依赖分析及时发现新的无效依赖被引入。9.2 自动清理不能代替人工 review自动清理解决的是“哪些依赖完全没被引用”的问题但它无法判断“某些依赖虽然被引用了但业务上已经不再需要”。比如一个项目从 Vue 2 迁移到 Vue 3可能还存在少量兼容层代码引用了旧工具库。Bun 会发现它被 import所以不会清理。这类历史包袱需要人工处理。9.3 小项目先行再逐步扩展给团队的建议是第一周选一个非核心、无用户量的项目整个依赖安装和清理流程跑通第二周扩大到维护频率较低的后台系统稳定运行后再考虑核心业务项目。9.4 容器镜像构建里的优势Docker 容器里安装依赖最怕的就是依赖体积大、安装速度慢。Bun 的依赖安装速度快且能在构建后自动清理无效依赖缩小镜像尺寸。一个常见的 Dockerfile 示例FROM oven/bun:1 WORKDIR /app COPY package.json bun.lock ./ RUN bun install --frozen-lockfile COPY . . RUN bun build ./index.ts --outdir ./dist CMD [bun, run, ./dist/index.js]利用 Bun 的官方镜像配合依赖锁定和源码级清理可以做出更快、更小的容器镜像。10. 总结与下一步实践建议Bun 1.4 最值得关注的不是某个性能数字而是它把依赖治理从“人工定期清理”变成了“安装时默认执行”的能力。依赖管理工具的职责边界被真正拓宽了不只是忠实地安装你声明的包而是会反过来告诉你哪些声明已经失去了意义。如果你想亲手验证建议按下面的路径来第一步安装 Bun用bun --version确认版本。第二步新建一个测试项目故意安装两三个依赖但不在代码里引用。第三步运行bun install观察 Bun 是否能识别出这些无效依赖。第四步把 Bun 的内置测试运行器和打包器用起来感受一套工具链完成所有事情的体验。第五步确认稳定后再选一个真实项目试水。最后提醒一点不管工具怎么自动清理依赖治理始终需要人来把关。Bun 1.4 帮你扫掉了 80% 的机械性工作剩下的 20% —— 比如某个依赖到底还有没有业务价值仍然需要开发者根据业务上下文来判断。希望这篇内容能帮你少踩一些依赖管理方面的坑。建议收藏备用也欢迎在实际验证之后回来交流 Bun 1.4 在你的项目里清掉了多少个无效依赖。