Bun 简介与定位
本教程共 34 篇 · 第 1 篇 · 更新于 2026-08-06
本节目标:
- 说清楚「JavaScript 引擎」与「JavaScript 运行时」的区别,理解 Bun 处在哪一层。
- 掌握 Bun 的四大核心能力(运行时 / 包管理器 / 测试运行器 / 打包器)分别对应哪条命令。
- 能把 Bun 与 Node.js、npm、esbuild、ts-node 等工具的职责一一对应,讲清楚”Bun 替代了什么”。
- 判断自己的项目是否适合用 Bun,以及应该整体采用还是增量采用。
1.1 一句话定义
Bun 是一个面向 JavaScript / TypeScript 应用的一体化工具集(all-in-one toolkit),以单个无外部依赖的可执行文件 bun 的形式发布。
这句定义里有三个关键词,值得逐个拆开。
「一体化」:日常前端 / 服务端开发需要的四类工具——运行代码、装依赖、跑测试、打包产物——在 Bun 里是同一个二进制文件里的四个子命令,不需要分别安装和配置。
「单个可执行文件」:安装 Bun 得到的就是一个 bun 可执行文件,它不依赖预装的 Node.js,也不需要 node_modules 里塞一堆构建工具。这一点决定了它在 CI、容器镜像、命令行工具分发等场景里的体积和启动优势。
「JavaScript / TypeScript」:Bun 把 TypeScript 和 JSX 当作一等公民,.ts、.tsx、.jsx 文件可以直接执行,不需要事先编译成 .js。
先来看四条最常用的命令,它们几乎就是这本教程的全部主线:
bun run index.tsx # 运行文件(TS / JSX 默认支持)
bun install # 安装依赖
bun build ./index.tsx # 打包产物
bun test # 运行测试
bunx cowsay 'Hello, world!' # 直接执行一个 npm 包提供的命令
Note本教程全程以 Bun v1.3.14 为版本基线。Bun 的小版本迭代很快(1.3.x 系列几乎每周都有更新),遇到本教程与你本机行为不一致时,请以
bun --version的实际版本和官方文档为准。
1.2 什么是「运行时」:引擎与运行时的分界线
要理解 Bun 的定位,先要分清两个经常被混用的概念。
JavaScript 引擎负责解析并执行符合 ECMAScript 规范的代码。今天最主流的两个开源引擎是 Google 开发的 V8(Chrome、Node.js 使用)和 Apple 开发的 JavaScriptCore(Safari 使用)。引擎本身只管”算数、造对象、跑函数”,它不知道什么是文件、什么是网络。
JavaScript 运行时在引擎之上补充了一整套与外部世界打交道的 API:
- 浏览器运行时提供 DOM、
fetch、WebSocket等 Web API,挂在window上; - Node.js 运行时提供
Buffer、process、__dirname等全局对象,以及node:fs、node:net、node:http等内置模块,并实现了一套早于 ES Modules 的 CommonJS 模块系统与解析算法。
Bun 属于运行时这一层,它使用 JavaScriptCore 作为引擎,同时实现了两套 API:一套是 Web 标准 API(fetch、WebSocket、ReadableStream、Headers、URL 等),另一套是 Node.js 兼容 API(process、Buffer、node:path、node:fs、node:http 等)。此外它还提供了自己的 Bun.* 命名空间,用于封装一些高频操作,例如 Bun.serve、Bun.file、Bun.write。
一个直观的对照:
// 三种写法在 Bun 里都能跑
import { readFileSync } from "node:fs"; // Node.js 兼容 API
const a = readFileSync("./data.txt", "utf8");
const b = await fetch("https://example.com"); // Web 标准 API
const c = await Bun.file("./data.txt").text(); // Bun 原生 API
这正是 Bun 的兼容性策略:你原来怎么写就怎么写,愿意换成 Bun 原生 API 时再换。
1.3 四大核心能力
Bun 的能力可以拆成四块,每一块都对应本教程后续的一整篇内容。
运行时(Runtime)—— bun run
直接执行 .js / .jsx / .ts / .tsx 文件。Bun 内置转译器(transpiler)会在执行前把 TypeScript 与 JSX 语法转换成普通 JavaScript,整个过程发生在内存里,不产生中间文件。
bun run index.ts
bun index.ts # 省略 run 关键字,行为完全相同
官方首页给出的说法是:Bun 的启动速度约为 Node.js 的 3 倍。这个差距来自进程启动开销,在 CLI 工具、Serverless 冷启动这类”跑一下就退出”的场景里最容易感知到。长时间运行的服务则要看具体负载,不能直接套用这个倍数。
包管理器(Package Manager)—— bun install
bun install 读取标准的 package.json,安装依赖到 node_modules,并生成锁文件 bun.lock(v1.2 起默认为文本格式,旧的二进制锁 bun.lockb 仅作兼容)。工作区(workspaces)通过 package.json 的 workspaces 字段声明,配合全局缓存使用。
速度上,官方基准显示 bun install 比 npm 快数倍到数十倍,具体倍数取决于依赖规模与缓存冷热。v1.3.14 又引入了隔离式 linker 的全局存储,热安装进一步提速。
Tip
bun install可以单独用在一个纯 Node.js 项目里——你不需要把运行时也换成 Bun。这就是 Bun 常说的「可增量采用(incrementally adoptable)」。
测试运行器(Test Runner)—— bun test
内置的测试运行器,API 风格与 Jest 兼容(describe / it / expect),原生支持 TypeScript、快照测试、DOM 测试与 watch 模式,不需要额外装 jest + ts-jest + babel 这一串工具链。
打包器(Bundler)—— bun build
内置打包器,支持 JS / TS / JSX / CSS,具备代码分割(splitting)、插件系统、HTML 入口导入,还能通过 bun build --compile 把项目打包成单个可执行文件。
bun build ./src/index.tsx --outdir=./dist --minify
1.4 Bun 替代了什么:与现有工具的职责对照
很多人第一次接触 Bun 会问:“它到底是 Node.js 的替代品,还是 webpack 的替代品?“答案是:它同时覆盖了多个工具的职责范围。下表把常见工具与 Bun 的对应能力列出来,便于建立映射关系。
| 你现在用的工具 | 承担的职责 | Bun 中的对应物 |
|---|---|---|
| Node.js | JavaScript 运行时 | Bun 运行时(bun run) |
| npm / yarn / pnpm | 依赖安装与脚本执行 | bun install / bun run <script> |
| npx | 临时执行包中的命令 | bunx |
| ts-node / tsx | 免编译执行 TypeScript | 运行时内置转译,直接 bun run app.ts |
| esbuild / Rollup / webpack | 打包与压缩 | bun build |
| Jest / Vitest | 单元测试 | bun test |
| dotenv | 加载 .env 文件 | 运行时自动加载 .env |
| nodemon | 文件变更后重启 | bun --watch / bun --hot |
Warning这张表说的是职责重叠,不是”谁比谁好”。npm、pnpm、esbuild、Jest、Vite 各自都有成熟的生态位与独特能力(例如 pnpm 的严格依赖隔离策略、Vite 的插件生态)。Bun 的价值主张是”把这几件事收敛到一个工具里,减少配置与依赖数量”,而不是宣称在每一项上都全面胜出。是否替换,取决于你的项目对生态、稳定性和统一性的权衡。
关于 Node.js 兼容性,需要一个客观的表述:Bun 的目标是 100% Node.js API 兼容,官方明确”如果一个包能在 Node.js 里工作却不能在 Bun 里工作,我们视为 Bun 的 bug”,并且每次发布前都会跑 Node.js 官方测试套件中的数千个用例。但这是一个持续推进中的目标,而不是已经完成的事实:截至 v1.3.14,node:fs、node:path、node:http、node:net 等核心模块已标记为完整实现,而 node:async_hooks、node:cluster、node:vm、node:worker_threads 等模块仍有已知差异。迁移前请查阅官方的 Node.js 兼容性列表,本教程第 4 章会详细展开。
1.5 设计目标
官方文档把 Bun 的设计目标概括为五条,理解它们有助于预判 Bun 在某个场景下的表现:
- 速度(Speed):从进程启动到依赖安装,全链路以性能为第一优先级。选用 JavaScriptCore 而非 V8,很大程度上就是出于启动速度的考虑。
- TypeScript 与 JSX 原生支持:
.ts/.tsx直接执行,转译由内置转译器完成。注意 Bun 只做语法剥离,不做类型检查——类型检查仍然应交给tsc或编辑器。 - ESM 与 CommonJS 双向兼容:Bun 推荐 ES Modules,但 npm 上仍有海量 CommonJS 包,因此两者可以在同一个项目里混用,甚至同一个文件里
import与require并存。 - Web 标准 API:
fetch、WebSocket、ReadableStream、Headers、URL等按 Web 规范实现,其中部分直接复用了 Safari 的实现,服务端与浏览器端的心智模型更接近。 - Node.js 兼容:包括 Node 风格的模块解析、全局对象与内置模块,属于持续推进中的长期目标。
1.6 什么场景适合用 Bun
适合优先考虑 Bun 的场景:
- 新开的 TypeScript 服务端项目:省掉
ts-node、nodemon、dotenv、jest这一整套配置,开箱即用。 - CLI 工具与脚本:进程启动快,还能用
bun build --compile打包成不依赖运行时的单文件可执行程序。 - CI 流水线加速:即使运行时仍用 Node.js,把
npm ci换成bun install通常也能显著缩短依赖安装时间。 - 中小型全栈应用:
Bun.serve内置了 HTML 入口、路由、WebSocket 与热更新,前后端可以跑在同一个进程里,省掉跨端口带来的 CORS 配置。 - 需要内置能力的场景:
bun:sqlite、内置 Redis 客户端、Bun.$(Shell)、Bun.password等,减少了对第三方原生模块的依赖。
需要谨慎评估的场景:
- 强依赖 Node.js 原生插件(N-API)或特定 Node 内部 API 的项目:兼容性需要逐项验证。
- 对生产环境稳定性要求极高、且已有成熟 Node.js 部署体系的存量系统:可以先从
bun install、bun test这类局部能力切入,不必一次性替换运行时。 - 深度绑定某个构建工具插件生态的前端工程:迁移打包器的成本可能高于收益。
TipBun 的采用不是”全有或全无”。推荐的路径是:先用
bun install替换依赖安装 → 再用bun test跑测试 → 最后评估是否把运行时切到 Bun。每一步都可以独立回退。
1.7 谁在用 Bun
几个可公开查证的例子:
- Midjourney:使用 Bun 内置的 WebSocket 服务端做大规模图片生成通知推送,并在前端开发中使用 Bun。
- Railway:其 Serverless 函数基于 Bun 的一体化工具链。
- Vercel:官方博客宣布平台支持 Bun 运行时。
此外,Bun 项目已加入 Anthropic,继续保持 MIT 开源协议与原有团队,并延续对标 Node.js 的路线。关于项目背景与演进方向(包括底层实现语言从 Zig 迁移到 Rust 的计划),本教程第 34 章会专门展开。
1.8 小结与常见误区
小结:
- Bun 是运行时层的产品,基于 JavaScriptCore 引擎,同时提供 Web 标准 API、Node.js 兼容 API 和
Bun.*原生 API。 - 四大能力对应四条命令:
bun run(运行)、bun install(装依赖)、bun test(测试)、bun build(打包)。 - 它的核心价值是「收敛工具链」与「快」,并且支持增量采用。
常见误区:
| 误区 | 事实 |
|---|---|
| ”Bun 是 npm 的替代品” | 不完整。Bun 同时替代了运行时、包管理器、测试运行器和打包器四类工具。 |
| “Bun 已经 100% 兼容 Node.js” | 100% 兼容是目标,不是现状。核心模块基本齐备,边缘模块仍有差异。 |
| “Bun 会做类型检查” | 不会。Bun 只剥离 TypeScript 语法,类型检查请继续交给 tsc。 |
| “用 Bun 就必须放弃 npm 生态” | 不必。Bun 使用标准 package.json,从 npm registry 安装包,node_modules 布局也是兼容的。 |
“bun run 只能跑 Bun 专属代码” | 不是。它同样可以运行为 Node.js 编写的 CommonJS 脚本。 |
下一章开始动手:在 macOS、Linux、Windows 上安装 Bun,并处理升级、卸载、CI 与镜像加速等实际问题。