Bun 运行时入门与生态概览:从零到一构建高性能应用

By | 2026年9月18日

为什么需要关注 Bun?

如果你是一名 JavaScript/TypeScript 开发者,可能已经对 Node.js 和 Deno 非常熟悉。但最近两年,一个名为 Bun 的运行时正在快速崛起。它由 Jarred Sumner 创建,目标是提供一个更快、更简洁、更集成的 JavaScript 工具链。

Bun 不仅是一个运行时,还内置了包管理器、打包器、测试运行器,甚至支持 TypeScript 和 JSX 开箱即用。根据官方基准测试,Bun 的启动速度和 HTTP 吞吐量都显著优于 Node.js。

这篇文章将带你从零开始,逐步了解 Bun 的核心功能,并通过一个完整的 REST API 示例,展示如何在实际项目中应用它。我们还会探讨 Bun 的生态现状、最佳实践以及一些常见的坑。

—

1. 安装 Bun

Bun 支持 macOS、Linux 和 Windows(WSL)。安装非常简单,一行命令即可:


# macOS / Linux
curl -fsSL https://bun.sh/install | bash

# Windows (使用 PowerShell)
irm bun.sh/install.ps1 | iex

安装完成后,验证版本:


bun --version
# 输出示例:1.1.34

💡 注意:Bun 的版本迭代非常快,建议定期使用 bun upgrade 更新到最新版。

—

2. 第一个 Bun 程序

创建一个简单的 hello.ts 文件:


const message: string = "Hello, Bun!";
console.log(message);

直接运行:


bun run hello.ts

你会发现 Bun 直接执行了 TypeScript 文件,无需任何编译步骤。这是 Bun 的一大亮点:原生支持 TypeScript 和 JSX。

—

3. 使用 Bun 作为包管理器

Bun 内置了包管理器,兼容 npm 生态,但速度更快。初始化项目:


mkdir bun-demo && cd bun-demo
bun init -y

这会生成 package.json、tsconfig.json 等文件。安装依赖:


bun add express
bun add -d @types/express

Bun 会生成 bun.lockb 二进制锁文件,比 package-lock.json 更紧凑。

💡 最佳实践:在 CI 环境中使用 bun install --frozen-lockfile 确保依赖一致性。

—

4. 构建一个 REST API

让我们用 Bun 原生 HTTP 服务器(Bun.serve)创建一个简单的用户管理 API。

创建 server.ts:


interface User {
  id: number;
  name: string;
  email: string;
}

const users: User[] = [
  { id: 1, name: "Alice", email: "alice@example.com" },
  { id: 2, name: "Bob", email: "bob@example.com" },
];

const server = Bun.serve({
  port: 3000,
  async fetch(req) {
    const url = new URL(req.url);

    // GET /users
    if (req.method === "GET" && url.pathname === "/users") {
      return Response.json(users);
    }

    // GET /users/:id
    const match = url.pathname.match(/^\/users\/(\d+)$/);
    if (req.method === "GET" && match) {
      const id = parseInt(match[1]);
      const user = users.find((u) => u.id === id);
      if (!user) {
        return new Response("User not found", { status: 404 });
      }
      return Response.json(user);
    }

    // POST /users
    if (req.method === "POST" && url.pathname === "/users") {
      const body = await req.json();
      const newUser: User = {
        id: users.length + 1,
        name: body.name,
        email: body.email,
      };
      users.push(newUser);
      return Response.json(newUser, { status: 201 });
    }

    return new Response("Not Found", { status: 404 });
  },
});

console.log(`Server running at http://localhost:${server.port}`);

运行:


bun run server.ts

测试 API:


curl http://localhost:3000/users
curl http://localhost:3000/users/1
curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d '{"name":"Charlie","email":"charlie@example.com"}'

你会发现 Bun.serve 的 API 非常简洁,且性能出色。根据官方基准,它比 Node.js 的 HTTP 模块快数倍。

—

5. 使用 Bun 测试

Bun 内置了测试运行器,语法类似 Jest,但速度更快。创建 server.test.ts:


import { describe, expect, test, beforeAll, afterAll } from "bun:test";

let server: any;

beforeAll(() => {
  // 启动测试服务器
  server = Bun.serve({
    port: 3001,
    fetch: (req) => {
      if (new URL(req.url).pathname === "/users") {
        return Response.json([{ id: 1, name: "Alice" }]);
      }
      return new Response("Not Found", { status: 404 });
    },
  });
});

afterAll(() => {
  server.stop();
});

describe("User API", () => {
  test("GET /users returns list", async () => {
    const res = await fetch("http://localhost:3001/users");
    const data = await res.json();
    expect(res.status).toBe(200);
    expect(data).toHaveLength(1);
    expect(data[0].name).toBe("Alice");
  });

  test("unknown route returns 404", async () => {
    const res = await fetch("http://localhost:3001/unknown");
    expect(res.status).toBe(404);
  });
});

运行测试:


bun test

Bun 的测试运行器支持 TypeScript、JSX、模拟(mock)等,且无需额外配置。

—

6. 打包与构建

Bun 也可以作为打包器使用。例如,将 server.ts 打包成单个文件:


bun build ./server.ts --outdir ./dist --target bun

对于前端项目,可以指定 --target browser:


bun build ./src/index.tsx --outdir ./dist --target browser --minify

Bun 的打包器速度极快,且支持代码分割、Tree Shaking 等特性。

—

7. 生态概览与兼容性

Bun 的目标是兼容 Node.js 生态。目前,大部分 npm 包都可以直接在 Bun 中运行。但仍有少数包依赖 Node.js 内部模块或原生插件,可能无法工作。

兼容性现状:

  • 核心 Node.js 模块(fs、path、http 等)已实现。
  • node-gyp 原生模块支持正在完善中。
  • 许多流行框架(Express、Hono、Elysia)已适配 Bun。

Bun 专属生态:

  • Elysia:一个为 Bun 设计的快速 Web 框架。
  • Bun SQLite:内置 SQLite 驱动,无需安装。
  • Bun FFI:直接调用 C 函数。

💡 建议:在新项目中可以大胆尝试 Bun;对于现有大型项目,建议先进行兼容性测试。

—

8. 常见坑与最佳实践

坑 1:环境变量加载

Bun 会自动加载 .env 文件,但不会覆盖已存在的环境变量。如果需要强制覆盖,使用 --env-file 或手动处理。

坑 2:TypeScript 配置

Bun 使用自己的 TypeScript 转译器,某些 tsconfig.json 选项可能不被支持。建议参考官方推荐的配置:


{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "types": ["bun-types"],
    "strict": true,
    "skipLibCheck": true
  }
}

坑 3:与 Node.js 的差异

  • Bun.serve 的 fetch 函数返回 Response 对象,而非 Node.js 的 IncomingMessage。
  • 文件系统 API 略有不同,例如 Bun.file() 返回 BunFile 对象。

最佳实践

  • 使用 bun --watch 实现热重载。
  • 在 package.json 中定义脚本,如 "start": "bun run server.ts"。
  • 利用 Bun.env 访问环境变量。

—

9. 总结与下一步

Bun 是一个令人兴奋的运行时,它通过集成工具链和极致的性能,为 JavaScript 开发带来了新的可能。本文介绍了安装、包管理、HTTP 服务、测试、打包等核心功能,并给出了一个完整的 REST API 示例。

下一步学习方向:

  • 探索 Elysia 框架构建更复杂的应用。
  • 使用 Bun 的 SQLite 驱动进行数据持久化。
  • 了解 Bun 的插件系统与 FFI。

Bun 仍在快速发展,建议关注官方博客和 GitHub 仓库,及时获取最新动态。

—

延伸阅读: