一、概览与提问(SQ3R · Survey & Question)

SQ3R 第一步:快速浏览全貌,提出关键问题。

什么是 Bun?

Bun 是一个面向 JavaScript 和 TypeScript 应用的一体化工具链(all-in-one toolkit)。它以单个可执行文件 bun 的形式发布,无需额外依赖。Bun 的核心是 Bun 运行时(Runtime)——一个快速的 JavaScript 运行时,被设计为 Node.js 的直接替代品(drop-in replacement)。它使用 Zig 语言编写,底层由 Apple 的 JavaScriptCore 引擎驱动,显著降低了启动时间和内存占用。

Bun 不仅仅是一个运行时。它同时包含:

  • 运行时(Runtime):直接执行 JavaScript/TypeScript 文件,TS 和 JSX 开箱即用
  • 包管理器(Package Manager):快速安装、workspaces、overrides、安全审计
  • 测试运行器(Test Runner):Jest 兼容、TypeScript 优先、快照测试、DOM 测试、watch 模式
  • 打包器(Bundler):原生打包 JS/TS/JSX,支持代码分割、插件、HTML 导入
bun run index.tsx       # TS 和 JSX 开箱即用
bun install <pkg>       # 安装包
bun build ./index.tsx   # 打包项目
bun test                # 运行测试
bunx cowsay 'Hello!'    # 执行 npm 包

核心问题

在深入之前,带着这些问题阅读:

  1. Bun 与 Node.js 有什么本质区别?为什么要换?
  2. Bun 的运行时为什么比 Node.js 快?
  3. Bun 的包管理器和 npm/yarn/pnpm 相比有什么优势?
  4. 如何将现有的 Node.js 项目迁移到 Bun?
  5. Bun 的打包器能否替代 webpack/esbuild?
  6. Bun 的测试运行器能否替代 Jest?
  7. Bun 在生产环境中是否已经足够成熟?

技术全景图

Bun 工具链
├── 运行时(Runtime)
│   ├── JavaScriptCore 引擎(来自 Safari)
│   ├── Zig 编写的转译器和运行时
│   ├── TypeScript / JSX 原生支持
│   ├── ESM + CommonJS 兼容
│   └── Web 标准 API(fetch, WebSocket, ReadableStream)
├── 包管理器(Package Manager)
│   ├── bun install(25x 快于 npm)
│   ├── workspaces / monorepo
│   ├── 全局缓存 + 硬链接/克隆
│   └── 安全:默认不执行依赖的生命周期脚本
├── 测试运行器(Test Runner)
│   ├── Jest 兼容 API
│   ├── 快照测试 / 生命周期钩子
│   ├── watch 模式 / 覆盖率
│   └── DOM 测试(happy-dom)
└── 打包器(Bundler)
    ├── JS/TS/JSX/CSS/HTML
    ├── 代码分割 / Tree shaking
    ├── 插件系统
    ├── 单文件可执行文件
    └── 全栈开发服务器

二、用最简单的话说清楚(费曼学习法)

如果你不能用简单的语言解释一件事,说明你还没有真正理解它。

核心概念讲解

Bun 就像一个瑞士军刀

想象你是一个木匠。以前你需要一把锤子(Node.js)、一个工具箱(npm)、一个测试仪(Jest)和一个打包机(webpack)。现在,Bun 就像一把瑞士军刀——一个工具搞定所有事情。你不需要分别安装和维护四个不同的工具,一个 bun 命令就够了。

运行时 = 引擎 + 环境API

JavaScript 本身只是一门语言的规范。JavaScript 引擎负责执行代码(如 Google 的 V8、Apple 的 JavaScriptCore)。但代码需要和外部世界交互——读文件、发网络请求——这些由运行时提供。

  • 浏览器的运行时提供 windowdocument 等 API
  • Node.js 的运行时提供 fshttpBuffer 等 API
  • Bun 的运行时提供与 Node.js 兼容的 API,同时实现了 Web 标准 API
// Bun 同时支持 Node.js 风格和 Web 标准 API
import { readFileSync } from "fs"; // Node.js API
const response = await fetch("https://api.example.com"); // Web 标准 API

包管理器 = 更快的 npm

# npm 安装:约 170ms 启动时间
npm install
 
# Bun 安装:约 6ms 启动时间——快 28 倍
bun install

为什么这么快?Bun 使用全局缓存 + 硬链接(Linux)或 clonefile(macOS),避免重复下载和复制文件。

测试运行器 = 更快的 Jest

import { expect, test } from "bun:test";
 
test("2 + 2", () => {
  expect(2 + 2).toBe(4);
});

API 几乎和 Jest 一样,但运行速度更快,因为测试直接在 Bun 运行时中执行,没有 Node.js 的启动开销。

打包器 = 更快的 esbuild

bun build ./index.tsx --outdir ./out

Bun 的打包器在 esbuild 的 three.js 基准测试中表现更快。支持 JS/TS/JSX/CSS/HTML,开箱即用。

类比与比喻

概念类比
Bun 运行时一个翻译速度更快的同声传译员(JavaScriptCore 比 V8 启动快 4 倍)
Bun 包管理器一个有全局仓库的快递员(缓存 + 硬链接,不用每次重新下载)
Bun 测试运行器一个用 Jest 语法但跑得更快的学生考试系统
Bun 打包器一个把散落文件打包成一个包裹的快递打包机
bunfig.tomlBun 的"设置面板",就像 .npmrc 之于 npm

常见误解澄清

误解 1:"Bun 只能在 macOS/Linux 上用" 事实:Bun 完整支持 Windows。在 Windows 上,Bun 使用自己的 shell 来支持 bash 风格语法。

误解 2:"Bun 不兼容 Node.js 生态" 事实:Bun 旨在实现与 Node.js 的完全兼容。支持 Node.js 内置模块(fspathhttp 等)和全局变量(processBuffer)。这是持续进行的工作,但大部分 npm 包可以直接在 Bun 中运行。

误解 3:"Bun 不适合生产环境" 事实:Bun 已被众多公司在生产环境中使用,并支持部署到 AWS Lambda、Google Cloud Run、Vercel、Railway 等主流平台。

误解 4:"用了 Bun 就不能再用 npm 包了" 事实:Bun 的包管理器完全兼容 npm 生态。如果你的项目有 package.jsonbun install 可以直接工作,几乎零修改。

三、锥形深入(西蒙学习法)

集中精力、目标导向、锥形深入——从核心开始,逐步扩展到周边。

第一层:核心基础

1. 安装 Bun

# macOS / Linux / WSL
curl -fsSL https://bun.sh/install | bash
 
# Windows
powershell -c "irm bun.sh/install.ps1 | iex"
 
# 使用 npm
npm install -g bun
 
# 使用 Homebrew
brew install oven-sh/bun/bun
 
# 使用 Docker
docker pull oven/bun

安装后验证:

bun --version

2. 运行时基础

Bun 运行时是 Bun 的核心。它使用 JavaScriptCore 引擎(Apple 为 Safari 开发的引擎),在大多数情况下比 V8(Node.js 使用)启动更快、运行更快。

# 运行文件
bun run index.js
bun run index.ts      # TypeScript 直接运行
bun run index.tsx     # JSX 直接运行
 
# 简写:可以省略 run
bun index.tsx
 
# 运行 package.json 脚本
bun run dev
bun run build
 
# watch 模式
bun --watch run index.tsx

性能对比(Linux Hello World):

命令启动时间
bun hello.js5.2ms
node hello.js25.1ms

为什么快? Zig 语言编写 + JavaScriptCore 引擎 + 原生转译器,没有 Node.js 的 V8 启动开销。

3. 包管理器

Bun 的包管理器设计为 npm、yarn、pnpm 的直接替代品,速度提升最高 25 倍。

# 安装所有依赖
bun install
 
# 添加包
bun add react
bun add react@19.1.1    # 指定版本
bun add -d typescript    # 开发依赖
 
# 移除包
bun remove react
 
# 全局安装
bun install -g cowsay
 
# CI/CD 模式(冻结锁文件)
bun ci
# 等同于 bun install --frozen-lockfile

安全特性:Bun 默认不执行安装依赖的生命周期脚本(如 postinstall),避免供应链攻击。如果需要允许某个包执行脚本,需要在 package.json 中声明:

{
  "trustedDependencies": ["esbuild", "sharp"]
}

安装策略

# 提升模式(传统 npm 行为)
bun install --linker hoisted
 
# 隔离模式(类似 pnpm,防止幽灵依赖)
bun install --linker isolated

4. 测试运行器

Bun 内置了 Jest 兼容的测试运行器,支持 TypeScript、生命周期钩子、快照测试、DOM 测试。

import { expect, test, describe } from "bun:test";
 
describe("数学运算", () => {
  test("加法", () => {
    expect(1 + 1).toBe(2);
  });
 
  test("异步测试", async () => {
    const data = await fetch("/api/data");
    expect(data.ok).toBe(true);
  });
});
# 运行所有测试
bun test
 
# 运行特定文件的测试
bun test ./test/math.test.ts
 
# 按名称过滤测试
bun test --test-name-pattern "addition"
 
# watch 模式
bun test --watch
 
# 并发执行
bun test --concurrent
 
# 覆盖率报告
bun test --coverage

测试文件匹配模式:*.test.{js|jsx|ts|tsx}*_test.**.spec.**_spec.*

生命周期钩子:

import { beforeAll, beforeEach, afterEach, afterAll, test } from "bun:test";
 
beforeAll(() => {
  /* 所有测试前执行一次 */
});
beforeEach(() => {
  /* 每个测试前执行 */
});
afterEach(() => {
  /* 每个测试后执行 */
});
afterAll(() => {
  /* 所有测试后执行一次 */
});

Mock 功能:

import { test, expect, mock } from "bun:test";
 
const random = mock(() => Math.random());
 
test("mock 测试", () => {
  const val = random();
  expect(random).toHaveBeenCalled();
  expect(random).toHaveBeenCalledTimes(1);
});

5. 打包器

Bun 的打包器是原生实现,在 esbuild 的基准测试中表现更快。

# CLI 使用
bun build ./index.tsx --outdir ./out
bun build ./index.tsx --outdir ./out --target browser
bun build ./index.tsx --outdir ./out --watch
// JavaScript API
const result = await Bun.build({
  entrypoints: ["./index.tsx"],
  outdir: "./out",
  target: "browser", // "browser" | "bun" | "node"
});
// result => { success: boolean, outputs: BuildArtifact[], logs: BuildMessage[] }

单文件可执行文件

# 将项目编译为独立可执行文件
bun build --compile ./index.tsx --outfile myapp
./myapp  # 直接运行,无需安装 Bun

第二层:进阶用法

1. HTTP 服务器(Bun.serve)

Bun 内置了高性能 HTTP 服务器,处理能力约为 Node.js 的 2.5 倍。

const server = Bun.serve({
  port: 3000,
  routes: {
    // 静态路由
    "/api/status": new Response("OK"),
 
    // 动态路由(参数)
    "/users/:id": (req) => {
      return new Response(`Hello User ${req.params.id}!`);
    },
 
    // 按 HTTP 方法分发
    "/api/posts": {
      GET: () => {
        const posts = db.query("SELECT * FROM posts").all();
        return Response.json(posts);
      },
      POST: async (req) => {
        const body = await req.json();
        return Response.json({ created: true, ...body }, { status: 201 });
      },
    },
 
    // 通配符路由
    "/api/*": Response.json({ message: "Not found" }, { status: 404 }),
  },
 
  // 未匹配路由的回退处理
  fetch(req) {
    return new Response("Not Found", { status: 404 });
  },
});
 
console.log(`Server running at ${server.url}`);

服务器管理

// 热重载路由(无需重启服务器)
server.reload({
  routes: {
    "/api/version": () => Response.json({ version: "2.0.0" }),
  },
});
 
// 停止服务器
await server.stop(); // 优雅停止
await server.stop(true); // 强制停止
 
// 获取客户端 IP
const address = server.requestIP(req);

2. 文件 I/O

Bun 提供了一套优化的文件读写 API。

// 读取文件
const text = await Bun.file("./hello.txt").text();
const buffer = await Bun.file("./data.bin").arrayBuffer();
const json = await Bun.file("./config.json").json();
 
// 检查文件是否存在
const exists = await Bun.file("./config.json").exists();
 
// 获取文件信息
const stat = await Bun.file("./data.bin").stat();
console.log(stat.size);
 
// 写入文件
await Bun.write("./output.txt", "Hello, World!");
await Bun.write("./data.bin", new Uint8Array([1, 2, 3]));
 
// 流式写入
const file = Bun.file("./large.txt");
const writable = file.writer();
writable.write("chunk 1\n");
writable.write("chunk 2\n");
writable.end();

3. SQLite(bun:sqlite)

Bun 原生内置了高性能 SQLite3 驱动,比 better-sqlite3 快 3-6 倍。

import { Database } from "bun:sqlite";
 
const db = new Database(":memory:"); // 或 "mydb.sqlite"
 
// 创建表
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)");
 
// 插入数据(预处理语句)
const insert = db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)");
insert.run({ $name: "Alice", $email: "alice@example.com" });
insert.run({ $name: "Bob", $email: "bob@example.com" });
 
// 查询数据
const user = db.query("SELECT * FROM users WHERE name = $name").get({ $name: "Alice" });
// => { id: 1, name: "Alice", email: "alice@example.com" }
 
const allUsers = db.query("SELECT * FROM users").all();
// => [{ id: 1, name: "Alice", ... }, { id: 2, name: "Bob", ... }]
 
// 事务
const insertMany = db.transaction((users) => {
  for (const user of users) {
    insert.run(user);
  }
});
 
insertMany([
  { $name: "Charlie", $email: "charlie@example.com" },
  { $name: "Diana", $email: "diana@example.com" },
]);

启用 WAL 模式提升性能

db.run("PRAGMA journal_mode = WAL;");

将查询结果映射到类

class User {
  name: string;
  email: string;
  get displayName() {
    return this.name.toUpperCase();
  }
}
 
const users = db.query("SELECT name, email FROM users").as(User).all();
console.log(users[0].displayName); // "ALICE"

4. WebSocket

Bun 原生支持 WebSocket,集成在 Bun.serve 中。

const server = Bun.serve({
  port: 3000,
  fetch(req, server) {
    // 升级 HTTP 请求为 WebSocket
    if (server.upgrade(req)) return;
    return new Response("WebSocket upgrade failed", { status: 500 });
  },
  websocket: {
    open(ws) {
      console.log("客户端已连接");
      ws.subscribe("chat");
    },
    message(ws, message) {
      // 发布消息到所有订阅 "chat" 的客户端
      server.publish("chat", message);
    },
    close(ws) {
      console.log("客户端已断开");
      ws.unsubscribe("chat");
    },
  },
});

5. 环境变量

Bun 自动加载 .env 文件,无需安装 dotenv。

// 直接读取,.env 文件自动加载
const apiKey = process.env.API_KEY;
const dbUrl = process.env.DATABASE_URL;
 
// 也可以从指定文件加载
// bun --env-file=.env.production run index.ts

6. Shell 脚本

Bun 提供了内置的 Shell API,可以从 JavaScript 中运行 Shell 命令。

import { $ } from "bun";
 
// 运行命令
const result = await $`echo "Hello, World!"`.text();
console.log(result); // "Hello, World!\n"
 
// 管道
const files = await $`ls`.text();
const filtered = await $`grep .ts <<< ${files}`.text();
 
// 带错误处理
try {
  await $`git push`;
} catch (e) {
  console.error("Push failed:", e);
}

7. 进程管理(Bun.spawn)

// 启动子进程
const proc = Bun.spawn(["echo", "Hello"], {
  stdout: "pipe",
  stderr: "pipe",
});
 
const text = await new Response(proc.stdout).text();
console.log(text); // "Hello\n"
 
const exitCode = await proc.exited;
console.log(`Exit code: ${exitCode}`);

8. FFI(外部函数接口)

Bun 可以直接调用 C 库函数,无需编写原生绑定。

const lib = dlopen("./mylib.so", {
  add: {
    args: ["int", "int"],
    returns: "int",
  },
});
 
console.log(lib.symbols.add(1, 2)); // 3

第三层:深度解析

1. JavaScriptCore vs V8:为什么 Bun 更快

Bun 使用 Apple 的 JavaScriptCore(JSC)引擎,而非 Google 的 V8。关键差异:

特性JavaScriptCore(Bun)V8(Node.js)
启动速度更快(~5ms)较慢(~25ms)
内存占用更低更高
JIT 编译更激进的优化渐进式优化
开发者Apple(Safari)Google(Chrome)

为什么启动快? JSC 的解释器启动成本更低,而 V8 需要较长时间来初始化 JIT 编译管道。

2. Zig 语言的优势

Bun 使用 Zig 编写运行时和转译器。Zig 的优势:

  • 无隐藏控制流:没有默认异常处理、没有隐式分配,代码行为完全可预测
  • 编译时计算:可以在编译期执行代码,优化性能
  • 与 C 互操作:Zig 可以直接导入 C 头文件,无需 FFI 绑定
  • 小二进制体积:Zig 编译出的二进制文件更小

3. Node.js 兼容性

Bun 致力于实现与 Node.js 的完全兼容。当前支持状态:

已支持的 Node.js API

  • 内置模块:fspathhttphttpscryptoosneturlutilstreambuffereventschild_process
  • 全局变量:processBuffer__dirname__filename
  • Node-API(N-API):支持原生 C++ 插件
  • CommonJS 和 ES Modules

迁移建议

# 步骤 1:在现有 Node.js 项目中安装 Bun
npm install -g bun
 
# 步骤 2:用 Bun 安装依赖(生成 bun.lock)
bun install
 
# 步骤 3:用 Bun 运行脚本
bun run dev    # 替代 npm run dev
bun test       # 替代 npm test
 
# 步骤 4:如果某个脚本使用 Node.js CLI 工具,用 --bun 标志
bun run --bun vite

兼容性注意点

  • 这是持续进行的工作,并非所有 Node.js API 都已实现
  • 大部分 npm 包可以直接运行
  • 使用 process.versions.bun 检测是否在 Bun 中运行

4. 插件系统

Bun 提供了统一的插件 API,可以同时扩展运行时和打包器。

// bunfig.toml 中配置插件路径,或直接在代码中使用
const plugin = Bun.plugin({
  name: "my-plugin",
  target: "browser",
  setup(build) {
    build.onLoad({ filter: /\.custom$/ }, (args) => {
      const content = Bun.file(args.path).text();
      return {
        contents: `export default ${JSON.stringify(content)}`,
        loader: "js",
      };
    });
  },
});

5. bunfig.toml 配置

Bun 使用 bunfig.toml 作为配置文件,支持运行时、包管理器和测试运行器的配置。

# bunfig.toml
 
# 运行时配置
[run]
# 预加载模块
preload = ["./setup.ts"]
 
# 包管理器配置
[install]
# 是否安装可选依赖
optional = true
# 是否安装开发依赖
dev = true
# 安装策略
linker = "hoisted"
# 最小发布年龄(防供应链攻击)
minimumReleaseAge = 259200
 
# 测试配置
[test]
# 覆盖率
coverage = true
# 重试次数
retry = 3
# 超时时间(毫秒)
timeout = 5000

6. 全栈开发与 HTML 导入

Bun 支持直接导入 HTML 文件,实现全栈应用开发:

import myReactApp from "./index.html";
 
Bun.serve({
  routes: {
    "/": myReactApp,
    "/api/data": () => Response.json({ message: "Hello" }),
  },
});
  • 开发模式bun --hot):按需打包,支持热模块替换(HMR)
  • 生产模式bun build):预构建所有资源,零运行时打包开销

7. Workers(多线程)

Bun 支持 Worker API 来创建多线程应用:

const worker = new Worker(new URL("./worker.ts", import.meta.url));
 
worker.postMessage({ type: "process", data: [1, 2, 3] });
 
worker.onmessage = (event) => {
  console.log("Worker 结果:", event.data);
};

Worker 在独立线程中运行,与主线程共享 I/O 资源。

四、要点笔记(康奈尔笔记法)

关键概念速查表

线索/关键词详细笔记
Bun 是什么一体化 JS/TS 工具链:运行时 + 包管理器 + 测试器 + 打包器,单个可执行文件
JavaScriptCoreApple 为 Safari 开发的 JS 引擎,启动比 V8 快约 4 倍
ZigBun 运行时和转译器的编写语言,高性能、无隐藏控制流、与 C 直接互操作
Node.js 兼容支持 Node.js 内置模块和全局变量,大部分 npm 包可直接运行
ESM + CJS同时支持 ES Modules 和 CommonJS,推荐 ESM
Web 标准 API原生实现 fetch、WebSocket、ReadableStream、Headers、URL 等
自动加载 .env无需 dotenv,Bun 自动读取 .env 文件
安全包管理默认不执行依赖的生命周期脚本,需在 trustedDependencies 中声明
WAL 模式SQLite 的 Write-Ahead Logging,大幅提升并发读写性能
单文件可执行bun build --compile 可生成独立可执行文件,无需安装 Bun

核心 API 速查

API / 命令用途示例
bun run <file>运行 JS/TS 文件bun run index.tsx
bun install安装依赖bun install / bun add react
bun test运行测试bun test --watch
bun build打包项目bun build ./index.tsx --outdir ./out
bunx <pkg>执行 npm 包bunx cowsay 'Hello'
Bun.serve()启动 HTTP 服务器Bun.serve({ port: 3000, fetch })
Bun.file()文件读取await Bun.file("./a.txt").text()
Bun.write()文件写入await Bun.write("./out.txt", "data")
bun:sqliteSQLite 数据库new Database(":memory:")
Bun.spawn()启动子进程Bun.spawn(["echo", "hi"])
Bun.plugin()注册插件Bun.plugin({ setup(build) {...} })
Bun.build()编程式打包await Bun.build({ entrypoints })
$Shell 命令await $echo hello.text()

本节总结

Bun 的核心价值在于一体化速度。它将 JavaScript/TypeScript 开发中最常用的四个工具(运行时、包管理器、测试器、打包器)整合到一个二进制文件中,并通过 JavaScriptCore 引擎和 Zig 语言实现了显著的性能提升。对于现有 Node.js 项目,Bun 提供了高度兼容的迁移路径,几乎可以零修改地切换使用。

五、复习与实践(SQ3R · Recite & Review)

核心要点回顾

  1. Bun 是 Node.js 的直接替代品:使用 JavaScriptCore 引擎,启动快 4 倍,HTTP 吞吐量高 2.5 倍
  2. 四个工具合一:运行时、包管理器、测试运行器、打包器,一个 bun 命令搞定
  3. 包管理器快 25 倍:全局缓存 + 硬链接/clonefile,默认安全(不执行依赖脚本)
  4. 测试兼容 Jest:API 几乎一致,迁移成本低
  5. SQLite 内置:高性能原生驱动,比 better-sqlite3 快 3-6 倍
  6. TypeScript 零配置:直接运行 .ts.tsx 文件,无需 ts-node
  7. Web 标准 API:fetch、WebSocket、ReadableStream 等开箱即用

动手练习

练习 1:创建一个 Bun 项目

bun init
# 选择 "Blank" 模板,然后:
bun add express
bun add -d @types/express

创建 index.ts

import express from "express";
const app = express();
 
app.get("/", (req, res) => {
  res.json({ message: "Hello from Bun!" });
});
 
app.listen(3000, () => console.log("Running on http://localhost:3000"));

运行:bun run index.ts

练习 2:写一个带数据库的 REST API

import { Database } from "bun:sqlite";
 
const db = new Database(":memory:");
db.run("CREATE TABLE todos (id INTEGER PRIMARY KEY, text TEXT, done INTEGER DEFAULT 0)");
 
const server = Bun.serve({
  port: 3000,
  routes: {
    "/api/todos": {
      GET: () => {
        const todos = db.query("SELECT * FROM todos").all();
        return Response.json(todos);
      },
      POST: async (req) => {
        const { text } = await req.json();
        db.run("INSERT INTO todos (text) VALUES (?)", [text]);
        return Response.json({ success: true }, { status: 201 });
      },
    },
    "/api/todos/:id": (req) => {
      const todo = db.query("SELECT * FROM todos WHERE id = ?").get(req.params.id);
      if (!todo) return new Response("Not Found", { status: 404 });
      return Response.json(todo);
    },
  },
});

练习 3:写测试

import { test, expect, beforeAll } from "bun:test";
import { Database } from "bun:sqlite";
 
let db: Database;
 
beforeAll(() => {
  db = new Database(":memory:");
  db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
  db.run("INSERT INTO users (name) VALUES ('Alice')");
});
 
test("查询用户", () => {
  const user = db.query("SELECT * FROM users WHERE name = ?").get("Alice");
  expect(user).toBeDefined();
  expect(user.name).toBe("Alice");
});
 
test("所有用户", () => {
  const users = db.query("SELECT * FROM users").all();
  expect(users).toHaveLength(1);
});

运行:bun test

常见陷阱

  1. --watch 标志位置bun --watch run index.ts(正确),而不是 bun run index.ts --watch(错误,--watch 会被传给脚本)
  2. SQLite 的 $param 前缀:默认绑定参数需要包含 $:@ 前缀,除非使用 strict: true 模式
  3. 依赖生命周期脚本不执行:如果某个包需要 postinstall 脚本才能工作,需要手动将其添加到 trustedDependencies
  4. 路由语法版本要求routes 对象语法需要 Bun v1.2.3+,更早版本需要使用 fetch 回调
  5. 热重载不是自动的:需要使用 --hot--watch 标志

延伸阅读