在2025 年 12 月,Bun 的开发团队正式宣布加入了Anthropic(也就是开发 Claude 的那家公司)。
这次收购在开发者圈子里引起了不小的轰动,因为它标志着 AI 模型公司开始深度垂直整合底层基础设施。
为什么 Anthropic 要买一个 JS 运行时?
最直接的原因是Claude Code。
- 极致的性能需求: Claude Code 是 Anthropic 推出的 AI 编程工具。AI 智能体(Agent)在辅助编程时,需要频繁地执行代码、跑测试、安装依赖。Node.js 的启动速度和执行效率在“模型-代码-反馈”的高频循环中显得太重。
- 单文件分发(Binary Distribution):Bun 能够将 JS/TS 项目打包成单个可执行文件。Claude Code 实际上就是作为一个Bun 编译的二进制文件 分发给数百万用户的。这意味着用户不需要预装 Node.js 环境,下载即用。
- 掌控底层:随着 Claude Code 的年收入(Run-rate)迅速突破10 亿美元,它已经成为了 Anthropic 的核心产品。为了确保这个产品的稳定性,Anthropic 必须掌控它的底层运行环境,而不是依赖第三方社区的决策。

所以现在正是学习bun的好时机
安装Bun
Bun 提供了一键式安装脚本。无论你在什么系统上,通常只需要一行命令:
macOS / Linux / WSL:
curl -fsSL https://bun.sh/install | bash
Windows (PowerShell):
powershell -c "irm bun.sh/install.ps1 | iex"
通过npm安装
npm install -g bun
安装完成后,输入 bun --version。如果看到版本号,恭喜你,你已经拥有了目前最快的 JS 运行时。
学习 Bun 不仅仅是换一个命令名,而是要理解它如何简化了传统的 JS 开发流程
彻底告别转译配置
在 Node.js 中,运行 TypeScript 需要ts-node或tsx,运行 JSX 需要配置 Babel。
在 Bun 中,这一切都是原生的。
- **知识点:**你可以直接运行
bun index.ts或bun component.tsx。 - **意义:**你的开发环境不再需要
tsconfig.json(除非为了类型检查)或复杂的 Webpack/Vite 配置来做初步预览。
极速包管理 (The Package Manager)
Bun 完全兼容 npm 的生态(node_modules 结构),但速度快得惊人。
- 常用命令:
bun install(等同于npm i)bun add <package>(等同于npm i <package>)
- **知识点:**Bun 使用了特殊的二进制锁文件
bun.lockb以实现极致的读取速度(当然你也可以导出为标准的yarn.lock)。
全能的 CLI 工具箱
Bun 奉行“全家桶”策略,它内置了许多原本需要第三方库的功能:
- **读取环境变量:**默认支持
.env,不需要dotenv库。直接使用process.env.PORT即可。 - **文件操作:**提供了高度优化的
Bun.file()API,比 Node 的fs快得多。 - **原生 Web API:**在服务端直接支持
fetch、Request、Response、WebSocket,无需引入node-fetch。
读取环境变量
在 Node.js 中,你通常需要npm install dotenv并在入口文件顶部写上require('dotenv').config()。
**在 Bun 中:**你只需要创建一个.env文件:
PORT=3000
API_KEY=fengfeng_666
在代码里面直接读取
// index.ts
console.log(`服务端口: ${process.env.PORT}`);
console.log(`我的密钥: ${process.env.API_KEY}`);
// 甚至可以使用 Bun 提供的更现代的写法
console.log(Bun.env.API_KEY);
装一下类型
bun add -d @types/bun
文件操作
Node.js 的fs模块历史悠久,但 API 相对繁琐且同步/异步混杂。Bun.file()采用了类似 Web 标准的Blob对象,且底层针对系统调用做了零拷贝(Zero-copy)优化。
// 1. 读取文件(返回一个 BunFile 对象,它是懒加载的,不占内存)
const file = Bun.file("input.txt");
// 2. 获取文本内容(异步)
const text = await file.text();
console.log("文件内容是:", text);
// 3. 获取二进制内容
const arrayBuffer = await file.arrayBuffer();
// 4. 极简的写入操作 (代替 fs.writeFileSync)
await Bun.write("output.txt", "这是 Teacher Fengfeng 写入的新内容");
// 5. 甚至可以直接把一个 URL 的内容流式写入文件
const response = await fetch("https://example.com");
await Bun.write("website.html", response);
如果你的await报红
是因为在传统的 JS/TS 环境中,只有当一个文件包含了import或export时,它才会被视为一个ES Module (ESM),而只有 ESM 才允许在顶层直接使用await。
虽然 Bun 默认就把所有文件当成模块处理(所以你能跑通),但编辑器里的 TypeScript 检查器还在坚持旧规则。
// 在最后加一个
export {}; // 加上这一行,警告立即消失
原生 Web API
Node.js 长期以来没有原生的fetch(直到最近几个版本才加入,且性能一般)。Bun 则是原生实现了 Web 标准,这意味着你的前端代码和后端代码可以高度复用。
// --- 发起 HTTP 请求 ---
const res = await fetch("https://api.github.com/repos/oven-sh/bun");
const data = await res.json();
console.log(`Bun 有 ${data.stargazers_count} 个 star!`);
// --- 建立一个简单的 WebSocket 服务 ---
Bun.serve({
port: 8080,
fetch(req, server) {
// 升级 HTTP 请求为 WebSocket
if (server.upgrade(req)) {
return;
}
return new Response("请使用 WebSocket 连接");
},
websocket: {
message(ws, message) {
console.log(`收到消息: ${message}`);
ws.send(`Bun 已收到: ${message}`);
},
open(ws) {
console.log("连接已开启");
},
},
});
高性能 HTTP 服务 (Bun.serve)
这是 Bun 的杀手锏。它内置了一个基于高性能 C++ 逻辑的 Web 服务器。
- 示例代码:
Bun.serve({
port: 3000,
fetch(req) {
return new Response("Welcome to Bun!");
},
});
- 知识点:
Bun.serve支持热重载(Hot Reloading),只需运行bun --hot index.ts,修改代码后服务器会瞬间更新,无需重启。
路由
如果你想做类似 Next.js 或 Nuxt.js 那样的基于文件的路由,Bun 已经内置了引擎,不需要手动写if。
const router = new Bun.FileSystemRouter({
style: "nextjs", // 支持 [id].ts 这种动态路由语法
dir: "./pages", // 指定路由文件目录
});
Bun.serve({
fetch(req) {
const match = router.match(req);
if (match) {
// 匹配到了 ./pages/index.ts 或 ./pages/user/[id].ts
return import(match.filePath).then(mod => mod.default(req, match));
}
return new Response("404", { status: 404 });
},
});
或者使用类似express的路由模式
bun install elysia
import {Elysia} from 'elysia';
new Elysia()
.get('/', () => '首页')
.get('/user/:id', ({params: {id}}) => `用户ID: ${id}`)
.post('/upload', ({body}) => {
return {status: 'success'};
})
.listen(3000);
https配置
在 Node.js 中配置 HTTPS 通常需要引入https模块并读取文件,而 Bun 直接在配置对象中通过tls字段实现:
Bun.serve({
port: 443,
fetch(req) {
return new Response("Hello from HTTPS!");
},
tls: {
// 可以是字符串、Buffer,或者是 Bun.file 对象
key: Bun.file("./key.pem"),
cert: Bun.file("./cert.pem"),
// 甚至可以配置证书链和密码
ca: [Bun.file("./ca.pem")],
passphrase: "fengfeng-secure",
},
});
性能与限制参数
这些参数对于构建稳健的后端服务(如你的网盘项目)至关重要,能有效防止恶意攻击或内存溢出。
hostname: 默认为0.0.0.0。你可以设置为localhost仅允许本地访问。maxRequestBodySize: 限制上传文件的大小(字节)。- 默认值: 128MB。
reusePort: (仅限 Linux) 允许开启多个进程监听同一个端口,实现负载均衡。
Bun.serve({
port: 3000,
hostname: "localhost",
maxRequestBodySize: 1024 * 1024 * 512, // 限制为 512MB
reusePort: true,
fetch(req) { ... }
});
环境与模式
development: 布尔值。如果设为true,Bun 会在页面上直接显示详细的错误堆栈信息(类似 PHP 的报错页面),方便调试。unix: 指定 Unix Domain Socket 的路径。如果设置了这个参数,port和hostname将被忽略。这在通过 Nginx 反向代理到本地进程时非常有用,速度比 TCP 更快。
Bun.serve({
unix: "/tmp/my-app.sock", // 使用 Unix 套接字通信
development: process.env.NODE_ENV !== "production",
fetch(req) { ... }
});
极其强大的原生 SQLite 支持
这是 Bun 区别于 Node.js 的一大特色。Bun 内置了高性能的 SQLite 驱动,不需要安装任何驱动或编译 C++ 插件,速度比better-sqlite3还要快。
import { Database } from "bun:sqlite";
const db = new Database(":memory:"); // 或 "mydb.sqlite"
const query = db.query("SELECT 'Hello Bun!' as message");
console.log(query.get()); // { message: "Hello Bun!" }
测试框架
测试也不再需要 Jest 或 Vitest。Bun 内置了bun test
- 语法完全兼容 Jest(
expect,test,describe)。 - 惊人的速度: 由于不需要启动复杂的转换层,运行速度通常比 Vitest 快 10-100 倍。
bun test # 自动寻找 *.test.ts 文件
Bun Shell:跨平台的脚本利器
在 Node.js 中写复杂的 Shell 脚本(如ls,mkdir)通常需要处理 Windows 和 Linux 的差异,或者引入zx库。Bun 内置了$符号。
import { $ } from "bun";
// 跨平台运行 shell 命令
await $`mkdir -p new_folder`;
const files = await $`ls`.text();
单文件打包 (Bun Shell & Bun.build)
正如你提到的 Claude Code 的分发方式,Bun 可以将你的整个应用打包成一个独立的二进制执行文件。
- 命令:
bun build ./index.ts --compile --outfile my-app - **意义:**你可以将这个
my-app文件发给任何没有安装 Node 或 Bun 的人,他们直接双击就能运行。这对于分发 AI Agent 工具或 CLI 工具简直是神技。
在 Node.js 时代,我们要分发一个工具,通常需要用户先安装 Node 环境,或者使用像pkg 这样极其沉重且容易出错的第三方包。
Bun 的--compile是原生集成的,它会将Bun 运行时、你的代码、以及node_modules** 中所有的依赖** 全部“揉”进一个几十兆的二进制文件中。
宏 (Macros) —— 进阶黑科技
这是 Bun 的杀手锏功能,允许在编译时执行代码。
你可以在打包时从数据库读取数据或进行复杂的计算,然后将结果直接硬编码进输出的 JS 文件中。
比如在编译的时候,读取package.json里面的版本
// utils.ts
import packageJson from "./package.json" assert { type: "json" };
/**
* 这个函数会被 Bun 在打包时执行
* 它必须返回一个可以被序列化的值(字符串、数字、对象、数组等)
*/
export function getVersion() {
console.log("正在打包... 正在提取版本号"); // 这行日志只会在你执行 bun build 时出现在控制台
return packageJson.version;
}
import { getVersion } from "./utils.ts" with { type: "macro" };
console.log(getVersion()); // 编译后直接变成字符串 "1.0.0"