4.1 最小 HTTP 服务器
Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello from Bun!");
},
});
console.log("http://localhost:3000");
启动后访问 http://localhost:3000——就这么 5 行。
为什么 fetch handler?
Bun 选用 Web Fetch API 作为服务器接口——Request/Response 对象和浏览器里的 fetch() 一模一样。好处:同一套代码能跑在 Bun / Cloudflare Workers / Deno 上,学一次用到处。
4.2 基本用法
import type { Server } from "bun";
const server: Server = Bun.serve({
port: 3000,
hostname: "0.0.0.0",
development: true, // 默认从 NODE_ENV 推断
async fetch(req, server) {
const url = new URL(req.url);
if (url.pathname === "/") return new Response("home");
if (url.pathname === "/api/hello")
return Response.json({ hello: "world" });
// POST 读 body
if (req.method === "POST") {
const body = await req.json();
return Response.json({ received: body });
}
return new Response("Not found", { status: 404 });
},
error(err) {
console.error(err);
return new Response("Server error", { status: 500 });
},
});
4.3 路由:routes 字段(Bun 1.2+)
Bun 1.2 起内置声明式路由,不用手写 URL 分支:
Bun.serve({
port: 3000,
routes: {
"/": new Response("Home"),
"/api/status": Response.json({ ok: true }),
// 按方法分发
"/users/:id": {
GET: (req) => Response.json({ id: req.params.id }),
DELETE: (req) => new Response(null, { status: 204 }),
},
// 通配
"/static/*": (req) => Bun.file(`./public${new URL(req.url).pathname}`),
},
// 未匹配 fallback
fetch() {
return new Response("Not found", { status: 404 });
},
});
req.params 自动解析 :id 这种参数,类型 { id: string }。
4.4 流式 Response
Bun.serve({
fetch() {
const stream = new ReadableStream({
async start(controller) {
for (let i = 0; i < 10; i++) {
controller.enqueue(new TextEncoder().encode(`chunk ${i}\n`));
await Bun.sleep(100);
}
controller.close();
},
});
return new Response(stream, {
headers: { "Content-Type": "text/plain" },
});
},
});
Server-Sent Events(SSE)、聊天流式输出都用这种 ReadableStream。
4.5 WebSocket
Bun.serve({
port: 3000,
fetch(req, server) {
// 升级到 WebSocket
const ok = server.upgrade(req, {
data: { userId: "123" }, // 关联到 ws 的自定义数据
});
if (ok) return; // 升级成功无需返回 Response
return new Response("Expected ws", { status: 400 });
},
websocket: {
open(ws) { console.log("opened", ws.data.userId); },
message(ws, msg) {
ws.send(`echo: ${msg}`);
ws.publish("room1", `${ws.data.userId}: ${msg}`);
},
close(ws) { console.log("closed"); },
},
});
发布-订阅(pub/sub)
Bun 的 WebSocket 内置 topic 订阅,多个 ws 可以订阅同一 topic,publish 群发:
ws.subscribe("room1"); // 加入房间
ws.publish("room1", "hi all"); // 广播给订阅者(除自己)
server.publish("room1", "server msg"); // 从 server 侧广播
4.6 TLS / HTTPS
Bun.serve({
port: 443,
tls: {
cert: Bun.file("./cert.pem"),
key: Bun.file("./key.pem"),
// 可选:CA、passphrase、dhParamsFile、serverName(SNI)
},
fetch() { return new Response("https!"); },
});
也支持多域名(SNI)——用 tls: [{ serverName: 'a.com', cert: ... }, { serverName: 'b.com', ... }]。
4.7 性能数字
| 服务器 | RPS(单核,Hello World) |
|---|---|
| Node http | ~40k |
| Node + Express | ~12k |
| Node + Fastify | ~50k |
| Bun.serve | ~120k |
实际业务吞吐差距会缩小(因为瓶颈往往在数据库/外部 IO),但 Bun 在冷启动和尾延迟上仍有明显优势。
4.8 上层框架:ElysiaJS / Hono
直接用 Bun.serve 写大型应用会很啰嗦——用专为 Bun 设计的框架:
- ElysiaJS:Bun 原生,TypeScript 优先,端到端类型安全,类 tRPC。
- Hono:多运行时(Bun/Deno/Node/Workers/Lambda),极简 API。
import { Elysia } from "elysia";
new Elysia()
.get("/", () => "home")
.get("/users/:id", ({ params }) => ({ id: params.id }))
.post("/echo", ({ body }) => body)
.listen(3000);
4.9 平滑停机
const server = Bun.serve({ /* ... */ });
process.on("SIGINT", () => {
server.stop(); // 拒绝新连接,等已有连接处理完
console.log("bye");
process.exit(0);
});
4.10 小结
Bun.serve({ fetch })一行起 HTTP,Web 标准 API 跨运行时。- Bun 1.2+ 的
routes字段提供声明式路由,:param/*支持。 - WebSocket 同实例
upgrade,内置 topic pub/sub。 - TLS + SNI 内置;性能约 3× Node。
- 大型项目上 ElysiaJS / Hono 框架。