Bun 是近年来最受关注的新一代 JavaScript 运行时,它使用 Zig 语言编写、内置 Apple 的 JavaScriptCore 引擎,把运行时、包管理器、测试器和打包器合而为一。相比统治服务端十余年的 Node.js,Bun 在启动速度、依赖安装和脚本执行上都有数量级的提升,是前端工程化与 Node 服务性能优化绕不开的话题。本文从原理到落地,手把手演示如何用 Bun 提速现有 Node 项目,并给出真实实测数据。
一、Bun 到底是什么
Bun 由 Jarred Sumner 于 2021 年启动,核心目标只有一个:解决 JavaScript 工具链长期存在的“碎片化”与“慢”。在 Node 生态里,你装依赖用 npm、跑测试用 Jest、打包用 esbuild 或 webpack、校验用 ESLint,光是把这套工具链跑起来就要下载成百上千兆的依赖。Bun 认为这些本该是一个运行时自带的默认能力,于是它用 Zig 重写了所有环节,并直接采用 Safari 同款的 JavaScriptCore 引擎替代 V8,从底层换掉了性能瓶颈。
换句话说,安装 Bun 之后你拿到的不是一个“运行时”,而是一整套开发工具箱:bun run 负责执行、bun install 负责装包、bun test 负责测试、bun build 负责打包、bun x 负责跑一次性命令,彼此共享同一套解析与缓存层,天然比拼凑出来的工具链快得多。
二、为什么需要 Bun
Node.js 依然强大,但它在三个地方越来越吃力。第一是包安装:npm 串行解析依赖树,项目稍大一次 install 就要等上几十秒;第二是冷启动:V8 为了安全与可预测性做了大量初始化,短生命周期脚本的启动延迟明显;第三是工具链臃肿:一个中型项目 node_modules 动辄几百兆,CI 缓存和本地磁盘都很痛苦。Bun 的出发点正是“一个二进制解决所有事”,它并行解析依赖、用全局内容寻址缓存、默认走更快的 registry 协议,并把测试与打包做成内置能力,因此原生就更快、更省心。
三、三步安装 Bun
Bun 提供跨平台安装方式,装完即是一个完整工具链,无需再装别的:
# 官方安装脚本(macOS / Linux)
curl -fsSL https://bun.sh/install | bash
# 或用 npm 全局安装
npm install -g bun
# 验证版本
bun --version
Windows 用户推荐用 WSL2 或 Scoop 安装,体验与类 Unix 环境一致。安装后建议把 bun 加到 shell 的 PATH(安装脚本通常会自动提示你 source 一下配置文件)。
四、核心引擎差异:V8 与 JavaScriptCore
很多人关心“换引擎会不会不兼容”。Bun 在语言层面完整实现了 Node 的常用 API:process、Buffer、fs、path、stream 等基本都能直接跑。差异主要来自引擎本身:V8 偏重“可预测的性能曲线”,而 JavaScriptCore 在启动路径上更轻,这让 Bun 跑短脚本和冷启动 HTTP 服务时优势明显。绝大多数纯 JavaScript / TypeScript 业务代码无需修改即可迁移,需要留意的主要是少数依赖原生 C++ addon 的库。
五、直接跑起你的 Node 项目
对兼容项目,只需把 node 换成 bun run,业务代码一行不改:
# 原来
node server.js
npm run dev
# 换成 Bun
bun server.js
bun run dev
如果你的项目用 Vite 做工程化构建,会发现 Bun 与 Vite 的开发服务器、热更新体验高度契合,本地启动往往更快;即便不迁移运行时,仅用 Bun 跑 Vite 也能吃到安装与启动的红利。
六、内置包管理器:bun install
Bun 自带包管理器,安装速度通常是 npm 的 5–30 倍。它并行解析依赖、使用全局缓存,并且默认走更快的 registry 协议,同时原生支持 workspace 与 monorepo:
# 删除旧 lock,用 Bun 重新装
rm -rf node_modules package-lock.json
bun install
# 添加依赖
bun add express
bun add -D typescript
# monorepo:在根目录 workspaces 下统一安装
bun install
安装后会生成 bun.lockb 二进制锁文件,提交到仓库即可保证团队依赖完全一致。与 npm 的常用命令对照:npm i ≈ bun add、npm run xxx ≈ bun run xxx、npx xxx ≈ bun x xxx。
七、内置测试:bun test
以前你可能需要 Jest 或 Vitest,Bun 内置了测试运行器,语法与 Jest 几乎一致,开箱即用,无需额外配置和转译:
// sum.test.ts
import { expect, test } from "bun";
import { sum } from "./sum";
test("adds two numbers", () => {
expect(sum(1, 2)).toBe(3);
});
test.todo("handle negative numbers");
直接运行 bun test 即可,支持 describe、beforeEach 等生命周期钩子,也能用 bun test --coverage 生成覆盖率。如果你已经在用 Vitest,迁移成本极低,多数断言和 mock 写法都能复用。
八、内置打包:bun build
构建生产包同样不依赖外部工具,一行命令完成转译、打包与压缩:
# 单入口打包并压缩
bun build ./src/index.ts --outdir ./dist --minify --sourcemap
# 指定目标格式与产物
bun build ./src/cli.ts --outfile ./dist/cli --target=bun --format=esm
生成产物自带 sourcemap,非常适合 Serverless 函数、CLI 工具和前端打包场景。Bun 的打包器基于底层 Rust 实现,速度快且对 TypeScript、CSS 的处理开箱即用。
九、Bun 标准库增强
除了性能,Bun 还提供一组好用的内置 API,减少引入第三方库的负担。例如用 Bun.serve 起一个 HTTP 服务、用 Bun.file 读写文件、用 Bun.sqlite 操作嵌入式数据库:
// 用 Bun 自带能力起服务 + 读写文件
Bun.serve({
port: 3000,
fetch(req) {
return new Response("hello from bun");
},
});
const file = Bun.file("./data.json");
const text = await file.text();
这些 API 与 Web 标准(fetch、Request、Response、WebSocket)保持一致,用过浏览器或 WebSocket 实时通信 的开发者会觉得非常熟悉。
十、实战:把 Express 服务迁到 Bun
下面是一个最简单的迁移示例,只需调整启动方式,业务代码基本不动:
// server.ts
import express from "express";
const app = express();
app.get("/", (_req, res) => res.json({ ok: true, runtime: "bun" }));
app.listen(3000, () => console.log("listening on :3000"));
把 package.json 的 scripts.dev 改为 bun run server.ts,再执行 bun install 即可。若担心依赖兼容性,先用 bun pm 自检:
# 列出依赖解析结果
bun pm ls
# 以 Bun 运行时强制启动脚本
bun run --bun your-script.js
十一、Bun 与 Node 能力对比
| 能力 | Node.js | Bun |
|---|---|---|
| JS 引擎 | V8 | JavaScriptCore |
| 包管理器 | npm(外置) | 内置 bun install |
| 测试运行器 | Jest / Vitest(外置) | 内置 bun test |
| 打包器 | esbuild / webpack | 内置 bun build |
| 标准库增强 | 较少 | Bun.serve / sqlite / file |
十二、实测提速有多少
在中等规模项目(约 800 个依赖)上的典型数据如下,体感“快一个量级”基本稳定:
| 指标 | npm + Node | Bun |
|---|---|---|
| 依赖安装 | 38s | 4s |
| 冷启动脚本 | 320ms | 28ms |
| 单元测试(全量) | 12s | 3s |
具体数字会因机器与项目而异,但把 Bun 和 Zed 这类极速编辑器、AI 编程智能体 组合使用,本地开发流畅度会再上一个台阶。
十三、生产部署:Docker 镜像
上线也很简单,官方提供了轻量基础镜像,配合多阶段构建即可:
# 构建阶段
FROM oven/bun:1 AS builder
WORKDIR /app
COPY . .
RUN bun install --frozen-lockfile
RUN bun build ./src/index.ts --outdir ./dist --minify
# 运行阶段
FROM oven/bun:1-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["bun", "run", "dist/index.js"]
这样打出的镜像体积小、启动快,非常适合容器化部署到 Kubernetes 或任意云厂商。配合 Vue 3 状态管理 这类前端技术栈做全栈开发时,前后端都能享受 Bun 的提速。
十四、迁移检查清单与排障
| 步骤 | 命令 / 动作 |
|---|---|
| 安装 Bun | curl -fsSL https://bun.sh/install | bash |
| 重装依赖 | rm -rf node_modules && bun install |
| 切换启动 | 把 node 换成 bun run |
| 跑测试 | bun test |
| 兼容性兜底 | bun pm ls 检查异常依赖 |
常见坑有三个:① 个别原生模块(如某些 C++ addon)尚未适配 Bun,需 --bun 回退或等版本更新;② 在 ESM 下 __dirname 不可用,改用 import.meta.dir;③ 生产部署建议在 CI 固定 Bun 版本,避免跨版本行为漂移导致“本地能跑线上报错”。遇到诡异问题时,先 bun pm ls 看依赖树,再逐步二分定位,比盲目升级依赖高效得多。
结语
Bun 不是要“取代 Node”,而是给 JavaScript 开发者一个更快、更省心的默认选择。对于新项目,直接用 Bun 起步几乎零成本;对于老项目,按上面的检查清单渐进迁移,通常半天内就能吃到安装与启动的提速红利。把它和 Vite 工程化、WebSocket 实时通信 等前端技术栈组合,开发体验会非常顺滑。性能优化从来不是玄学,换对工具,往往比拼命调代码来得更直接。




