Chapter 07

Bun 运行时集成

Hono 在 Bun 上的极致性能——零配置 SQLite、原生文件 API 与内置测试框架

Bun 简介

Bun 是 2023 年发布正式版的新一代 JavaScript/TypeScript 运行时,基于 JavaScriptCore(Apple 的 JS 引擎)构建,用 Zig 语言编写。它不只是运行时,更是一个完整的工具链:包管理器、打包器、测试框架全部内置。

Hono + Bun 是本地开发和小规模服务的黄金组合:Bun 提供极速启动和原生 TypeScript,Hono 提供最快的 HTTP 路由——无需任何配置即可开始。

快速创建 Hono + Bun 项目

# 官方脚手架
bun create hono my-bun-app
# 选择 bun 模板

cd my-bun-app
bun install
bun run dev  # 启动开发服务器(带热重载)
// src/index.ts — Bun 默认模板
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

export default app  // Bun 通过 export default 识别服务器
// package.json scripts
{
  "scripts": {
    "dev": "bun --hot run src/index.ts",  // 热重载
    "start": "bun run src/index.ts",
    "test": "bun test"
  }
}

自定义端口与 TLS

// 显式使用 Bun.serve() 进行更多配置
import { Hono } from 'hono'

const app = new Hono()
app.get('/', (c) => c.text('Hello'))

const server = Bun.serve({
  fetch: app.fetch,
  port: Number(process.env.PORT) || 3000,
  hostname: '0.0.0.0',

  // 可选:TLS 配置(本地 HTTPS)
  // tls: {
  //   cert: Bun.file('./certs/cert.pem'),
  //   key: Bun.file('./certs/key.pem'),
  // },
})

console.log(`Server started on http://localhost:${server.port}`)

Bun SQLite:零配置本地数据库

bun:sqlite 是 Bun 内置的 SQLite 客户端,无需安装任何依赖,性能比 better-sqlite3 快约 2.7 倍:

import { Hono } from 'hono'
import { Database } from 'bun:sqlite'  // 零依赖!

// 创建/打开数据库(文件路径 或 ':memory:')
const db = new Database('app.db')

// 创建表
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`)

// 预编译语句(性能最优)
const insertUser = db.prepare(`
  INSERT INTO users (name, email) VALUES ($name, $email)
  RETURNING *
`)

const getUserById = db.prepare(`
  SELECT * FROM users WHERE id = $id
`)

const listUsers = db.prepare(`
  SELECT * FROM users ORDER BY created_at DESC LIMIT $limit OFFSET $offset
`)

const app = new Hono()

app.get('/users', (c) => {
  const page = Number(c.req.query('page') ?? 1)
  const limit = 20
  const users = listUsers.all({
    $limit: limit,
    $offset: (page - 1) * limit
  })
  return c.json({ users })
})

app.post('/users', async (c) => {
  const { name, email } = await c.req.json<{ name: string; email: string }>()
  const user = insertUser.get({ $name: name, $email: email })
  return c.json(user, 201)
})

app.get('/users/:id', (c) => {
  const user = getUserById.get({ $id: c.req.param('id') })
  if (!user) return c.json({ error: 'Not found' }, 404)
  return c.json(user)
})

export default app

Bun 文件系统 API

// 读取文件(Bun.file 返回惰性引用,性能极高)
const file = Bun.file('./data/config.json')
const config = await file.json()     // 直接解析 JSON
const text = await file.text()       // 读取文本
const buffer = await file.arrayBuffer()  // 读取二进制

// 检查文件是否存在
const exists = await Bun.file('./data/config.json').exists()

// 写入文件
await Bun.write('./output.json', JSON.stringify({ key: 'value' }))
await Bun.write('./image.png', buffer)

// 在 Hono 路由中提供文件下载
app.get('/download/:name', (c) => {
  const file = Bun.file(`./uploads/${c.req.param('name')}`)
  // Bun.file 实现了 Body 接口,可直接传给 Response
  return new Response(file)
})

Bun 内置测试框架

Bun 内置了与 Jest 兼容的测试框架,无需安装任何依赖:

// src/index.test.ts
import { describe, it, expect, beforeAll } from 'bun:test'
import app from '.'

describe('Hono App', () => {
  it('GET / returns 200', async () => {
    // 使用 Hono 内置的测试方法(无需启动服务器)
    const res = await app.request('/')
    expect(res.status).toBe(200)
    expect(await res.text()).toBe('Hello Hono!')
  })

  it('GET /users returns user list', async () => {
    const res = await app.request('/users')
    expect(res.status).toBe(200)

    const body = await res.json()
    expect(body).toHaveProperty('users')
    expect(Array.isArray(body.users)).toBe(true)
  })

  it('POST /users creates a user', async () => {
    const res = await app.request('/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: 'Test User', email: 'test@example.com' }),
    })

    expect(res.status).toBe(201)
    const user = await res.json()
    expect(user.name).toBe('Test User')
    expect(user.email).toBe('test@example.com')
    expect(user).toHaveProperty('id')
  })

  it('returns 404 for unknown routes', async () => {
    const res = await app.request('/nonexistent')
    expect(res.status).toBe(404)
  })
})
# 运行测试
bun test

# 带覆盖率
bun test --coverage

# 监视模式
bun test --watch

Bun vs Node.js 性能对比

场景Node.js 22Bun 1.x优势
HTTP 吞吐量(Hono)~110k req/s~210k req/s+91%
进程启动时间~70ms~5ms14x
SQLite 100万行读取~0.8s~0.3s2.7x
包安装(热缓存)npm ~5s~180ms27x
文件读取(1GB)~1.5s~0.4s3.7x

Hono + Bun 的最佳定位:本地开发服务器(极速启动和热重载)、内部工具和脚本(SQLite + 文件 API 开箱即用)、边缘函数原型开发(代码直接迁移到 Cloudflare Workers)。生产环境大规模服务建议评估稳定性需求后再决定是否使用 Bun。