Bun — JS 全能运行时
是什么
Bun 是一个用 Zig 写的 JavaScript 全能运行时——把 Node.js + npm + bundler + transpiler + test runner 打包成一个二进制。
日常类比:以前出门要带相机 + 手电筒 + 笔记本三件设备,现在一台手机搞定。
你装一个 bun,就同时拥有:
bun run app.ts # 跑代码(替代 node + ts-node)bun install lodash # 装包(替代 npm / pnpm)bun build app.ts # 打包(替代 webpack / esbuild)bun test # 跑测试(替代 jest / vitest)不用装 typescript、ts-node、jest、webpack 这些工具——Bun 把它们全部收进一个二进制里。
为什么重要
不理解 Bun,下面这些事都没法解释:
- 为什么 2024 年突然有一堆人说”我把 Node 换成 Bun,启动快了好几倍”
- 为什么
bun install装 100 个包比 pnpm 还快 30 倍——明明 pnpm 已经够快了 - 为什么 Bun 文件里没看到
import 'http'也能Bun.serve起一个 HTTP server - 为什么有人说”Bun 是给前端工程师写后端的最低门槛”
Bun 的核心价值有四点:
- 启动快 4 倍:Node 启动 ~80ms,Bun ~30ms。原因是 Zig 写的 JIT + JavaScriptCore 引擎(不是 Node 用的 V8)
bun install快 30 倍:用全局二进制 cache + hardlink + 并行下载——和 pnpm 思路像但更激进- 内置一切:TypeScript / JSX / SQLite / 测试框架原生支持,不用配
tsconfig+babel+jest - Web 标准 API 是一等公民:
fetch/WebSocket/FormData直接用,Node 要等到 v18 才慢慢补齐
核心要点
Bun 之所以能”全能 + 快”,靠 三个底层选择:
-
用 Zig 写(不是 Rust 或 Go)
-
用 JavaScriptCore 引擎(不是 V8)
- JSC 是 Apple Safari 的引擎;V8 是 Chrome / Node 的引擎
- JSC 启动快、解释器优先、嵌入 API 小——Bun 选它就是为了冷启动速度
- 代价:V8 的 JIT 优化峰值更高,长跑服务计算密集场景略慢
-
包管理用全局 cache + hardlink
- 第一次装
lodash下载到全局~/.bun/install/cache/ - 第二次别的项目装
lodash不重新下载,hardlink 一份到node_modules/——磁盘 0 拷贝 - 这思路 pnpm 也用,但 Bun 走得更极端:连 metadata 都尽量并行处理
- 第一次装
实践案例
案例 1:30 秒起一个 React 项目
bun create react-app my-appcd my-appbun devbun dev 启动 dev server 从命令敲下到浏览器能访问 ~200ms。同样的 npm run dev ~2-3s 起步。
案例 2:跑 Jest 兼容的测试
math.test.ts:
import { test, expect } from "bun:test";
test("加法", () => { expect(1 + 1).toBe(2);});bun test # 不用装 jest,不用配 babel,不用 ts-jestAPI 和 Jest 几乎一样(describe / it / expect / mock)——直接搬现有 Jest 测试基本能跑。
案例 3:用 Bun 写 HTTP server
Bun.serve({ port: 3000, fetch(req) { return new Response("Hi"); },});逐部分解释:
Bun.serve是 Bun 内置 API,不用import 'http'fetch(req)接收一个标准 WebRequest对象,返回标准Response对象——这就是”Web 标准 API 一等公民”- 同样的代码逻辑在 Node 里要
http.createServer((req, res) => res.end(...)),写法和浏览器 API 完全不一样 - 用 Bun 写完这段,直接搬到 Cloudflare Workers / Deno Deploy 几乎不用改——因为它们都用 Web 标准 API
踩过的坑
-
Node 内置模块不全兼容:
fs/path/http这些常用的 OK;v8/vm/inspector这些低层模块模拟得不全。依赖 V8 inspector 协议的工具(Chrome DevTools profiling)跑不动。 -
JSC 与 V8 边角行为不一致:
RegExp部分高级特性(lookbehind 长度限制)有差异- 大数运算(
BigInt)在某些 corner case 下精度处理不同 WeakRef/FinalizationRegistry的 GC 时机由 JSC 决定,跨引擎写”靠 GC 触发”的代码不可靠
-
Bundler 输出不如 esbuild 干净:默认开 bundle + treeshake,但生成的代码会带额外的 polyfill 和 runtime helper。做 library 发布用 esbuild / rollup 仍然更干净。
-
生产环境还少(截至 2024 年逐步成熟):
- 长跑服务 + 99.99% SLA 场景,Node 的运维生态多 10 年
- 某些 native 模块(如
sharp的特定 patch)跑不动 - 大型团队技术栈迁移要观望——通常黑客松 / 小工具 / CLI 这些场景先用
适用 vs 不适用场景
适用:
- 新项目 startup / 黑客松 / 内部工具——启动快 + 配置零摩擦
- 替代 Jest 跑现有测试——
bun test兼容度够高 - 写 CLI 工具 / agent backend / 小型 HTTP API——单二进制部署超方便
- 学 bundler / parser 内部原理——Bun 源码是 Zig 写的,hot path 注释丰富
不适用:
- 生产环境长跑服务 + 高 SLA——Node 仍是更稳的选择
- 依赖某个特定 Node native 模块(如
sharp某些 patch)——直接跑不动 - 强依赖 Chrome DevTools 协议——JSC 的 inspector 协议跟 V8 不同
- 团队完全没人用过 Zig——出问题排查源码门槛高
历史小故事(可跳过)
- 2021 年:Jarred Sumner 一个人在 Twitter 上说”我要写一个比 Node 快 4 倍的 JS 运行时”——大家以为他疯了
- 2022 年 7 月:Bun 0.1 发布,benchmarks 显示真的比 Node 快——风向开始变
- 2023 年 9 月:Bun 1.0 发布,背后团队 Oven 拿到红杉投资
- 2024-2025:陆续支持 Windows / Workspaces / SQLite 内置 /
bun:testmock API——逐步进入”敢上生产”区间
不像 node-runtime 是 Ryan Dahl 把 V8 包进 C++ 让前端能写后端的产物,Bun 是”既然要重做一遍,干脆把工具链全打包”的回答。
学到什么
-
一个二进制 = 一条 pipeline:Node 是 4 个独立工具(runtime / npm / bundler / test runner)用 stdio 串起来;Bun 是 4 个 phase 共享同一个内存里的 AST。省掉序列化 / IPC / 4 次启动才是快的真正来源。
-
选语言 = 选 trade-off:Zig 没 GC + C ABI 互操作好;Rust borrow checker 严格但 hot path 写起来不直观;Go 简单但性能上限低。Bun 选 Zig 是赌”hot path 优化空间 > 语言成熟度”。
-
选引擎也是 trade-off:JSC 启动快但峰值优化弱;V8 启动慢但长跑性能强。短任务(CLI / 启动)选 JSC,长任务(数据处理)选 V8。
-
Web 标准 API 是新世代后端的最大公约数:Cloudflare Workers / Deno / Bun 都用
fetch/Response——你写一份代码能在三个 runtime 上跑。这是 Node 的http.createServer永远做不到的事。
延伸阅读
- 官方 docs:bun.sh/docs——产品功能完整清单
- 源码:github.com/oven-sh/bun——Zig 写的 lex / parse / bundle / test runner pipeline
- Jarred Sumner 的早期访谈:ChangeLog Podcast — Bun——讲为什么选 Zig 和 JSC
- zig —— Bun 的实现语言
- esbuild —— Bun lexer 的祖先(Go 实现,更易读)
关联
- zig —— Bun 的实现语言;选 Zig 是为 hot path 优化空间
- esbuild —— Bun 的 lexer fork 自 esbuild,注释都是从 Go 翻成 Zig 的
- swc —— Rust 阵营的 JS toolchain,与 Bun 是直接竞品
- pnpm ——
bun install的 hardlink 思路与 pnpm 一脉相承,但更激进 - node-runtime —— Bun 想取代的对象;保持兼容是 Bun 的核心策略
反向链接
- deno —— Deno — 安全优先的 JS/TS 运行时
- elysia —— Elysia — 长在 Bun 上的极致类型安全 Web 框架
- esbuild —— esbuild — 用 Go 写的极速 JS bundler
- hono —— Hono — 多运行时 Web 框架
- koa —— Koa — async/await + ctx 对象 + 洋葱模型 的极简 Node.js web 框架
- lightningcss —— lightningcss — 用 Rust 把 CSS 工具链一遍跑完的编译器
- meilisearch —— MeiliSearch — 开发者友好的搜索引擎
- pnpm —— pnpm — 全机器只存一份的 Node 包管理器
- postgres-js —— postgres.js — 写 SQL 但语法层就防注入的 Node 客户端
- quickjs —— QuickJS — 装进口袋的 JavaScript 引擎
- spin —— Spin — 用 WebAssembly 模块当 serverless handler 的开源框架
- swc —— SWC — Rust 写的 TS/JS 编译器
- vitest —— Vitest — Vite 原生测试框架