Bun 实战:用更快的 JavaScript 运行时提速 Node 项目

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.jsBun
JS 引擎V8JavaScriptCore
包管理器npm(外置)内置 bun install
测试运行器Jest / Vitest(外置)内置 bun test
打包器esbuild / webpack内置 bun build
标准库增强较少Bun.serve / sqlite / file

十二、实测提速有多少

在中等规模项目(约 800 个依赖)上的典型数据如下,体感“快一个量级”基本稳定:

指标npm + NodeBun
依赖安装38s4s
冷启动脚本320ms28ms
单元测试(全量)12s3s

具体数字会因机器与项目而异,但把 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 的提速。

十四、迁移检查清单与排障

步骤命令 / 动作
安装 Buncurl -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 实时通信 等前端技术栈组合,开发体验会非常顺滑。性能优化从来不是玄学,换对工具,往往比拼命调代码来得更直接。

上一篇 Zed 编辑器实战:用 Rust 打造极速开发体验
下一篇 JPMS 实战:用 Java 模块系统收敛依赖与强封装
最新评论
Docker 网络模式详解:bridge/host 生产选型 - FSData
Docker 网络模式详解:bridge/host 生产选型 - FSData
8月20日
[…] 注意最后那条:把端口绑定到 127.0.0.1,再由宿主机上的 Nginx 反代进来,比直接 -p 80:80 暴露安全得多,也方便统一做
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
8月20日
[…] Pinia 的工程化用法,可以参考我们之前的实战文章 《Vue3 组合式 API + Pinia:状态管理从入门到实战》,那里覆盖了 Sto
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
8月19日
[…] 状态,点一下就能起停容器,配合我们讲过的 Docker Compose 编排 […]
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
8月19日
[…] 缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
8月19日
[…] Docker 镜像部署。结合我们之前写的 Docker Compose 一键编排实战,可以在 CI […]