22.03-Bun部署

要点

  • Bun 是一个高性能的 JS 运行时,内置打包器和包管理器
  • Hono 原生支持 Bun,不需要额外适配器
  • Bun 的优势:启动快、内存占用低、内置 SQLite
  • 部署方式和 Node.js 类似,但可以用更少的工具链

内容

1. Bun 是什么

Bun 是一个用 Zig 写的 JS 运行时,目标是替代 Node.js,提供更快的速度和更好的开发体验。

特性Node.jsBun
引擎V8JavaScriptCore(Safari 的引擎)
启动速度中等
内置打包器有(bun build
包管理器npm/pnpm/yarn内置 bun
TypeScript需要编译原生支持
SQLite需要驱动内置 bun:sqlite

2. Hono 在 Bun 上跑

Hono 对 Bun 有原生支持,不需要适配器:

// src/index.ts
import { Hono } from 'hono'
 
const app = new Hono()
 
app.get('/', (c) => c.text('Hello Hono on Bun!'))
app.get('/api/users', (c) => c.json({ users: [] }))
 
export default app

直接运行:

// terminal
bun run src/index.ts

Bun 原生支持 TypeScript,不需要先编译。这是和 Node.js 的一个重要区别。

3. Bun 作为服务器

export default app 在 Bun 里会自动启动 HTTP 服务器。Bun 内部用的是 Bun.serve()

// src/index.ts
import { Hono } from 'hono'
 
const app = new Hono()
 
app.get('/', (c) => c.text('Hello!'))
 
// 方式 1:直接 export(Bun 自动处理)
export default app
 
// 方式 2:显式调用 Bun.serve
Bun.serve({
  fetch: app.fetch,
  port: 3000,
})

4. 构建和生产部署

虽然 Bun 可以直接运行 TypeScript,但生产环境通常还是先构建:

// terminal
# 构建(打包成单个文件)
bun build src/index.ts --target=bun --outdir=./dist
 
# 运行构建产物
bun run dist/index.js

bun build 会把所有依赖打包成一个文件,部署时只需要一个 dist/index.js

4.1 构建为独立可执行文件

Bun 还可以把项目编译成独立的可执行文件:

// terminal
# 编译成可执行文件
bun build src/index.ts --compile --outfile my-api
 
# 运行(不需要安装 Bun)
./my-api

编译后的文件包含了 Bun 运行时和你的代码,可以在没有 Bun 的服务器上直接运行。部署变得非常简单——把二进制文件传上去就行。

5. 进程管理

和 Node.js 一样,Bun 也需要进程管理工具。可以用 PM2:

// terminal
# PM2 支持 Bun
pm2 start src/index.ts --interpreter=bun --name my-api
 
# 或者用构建后的文件
pm2 start dist/index.js --interpreter=bun --name my-api

也可以用 Docker:

# Dockerfile
FROM oven/bun:1
 
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
 
COPY . .
RUN bun build src/index.ts --target=bun --outdir=./dist
 
EXPOSE 3000
CMD ["bun", "run", "dist/index.js"]

6. 内置 SQLite

Bun 内置了 SQLite 支持,不需要额外的驱动:

// src/db.ts
import { Database } from 'bun:sqlite'
 
const db = new Database('my-db.sqlite')
 
// 创建表
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL
  )
`)
 
// 插入
const insert = db.prepare('INSERT INTO users (name, email) VALUES ($name, $email)')
insert.run({ $name: 'Alice', $email: '[email protected]' })
 
// 查询
const select = db.prepare('SELECT * FROM users WHERE id = $id')
const user = select.get({ $id: 1 })

对于小型项目,Bun + 内置 SQLite 就是一个完整的后端栈,不需要外部数据库。

7. 和 Node.js 部署的对比

维度Node.jsBun
TypeScript 支持需要编译或 tsx原生支持
启动速度较慢
内存占用较高较低
包管理器npm/pnpm/yarn内置 bun
打包器需要 esbuild/webpack内置 bun build
SQLite需要 better-sqlite3内置 bun:sqlite
生态兼容性最好(npm 生态)大部分兼容,少数包有问题

Bun 的优势在速度和工具链集成度。劣势在生态兼容性——虽然大部分 npm 包都能用,但偶尔会遇到不兼容的情况。

8. 适用场景

Bun 适合这些场景:

  1. 新项目:不需要兼容旧代码,可以享受 Bun 的全部优势
  2. 性能敏感:启动速度和内存占用比 Node.js 好
  3. 小型后端:内置 SQLite + 内置打包,工具链简单
  4. 脚本和 CLI:Bun 跑脚本比 Node.js 快

不适合:

  1. 依赖大量 Node.js 原生模块:部分原生模块不兼容
  2. 需要极致稳定性:Bun 还在快速迭代,API 可能有变化
  3. 企业级项目:Node.js 的生态和社区支持更成熟

9. 小结

Bun 部署的核心:

  1. Hono 原生支持 Bun,不需要适配器
  2. 可以直接跑 TypeScript,不需要先编译
  3. bun build --compile 可以编译成独立可执行文件
  4. 内置 SQLite,小型项目不需要外部数据库
  5. 进程管理用 PM2(支持 Bun 作为解释器)

Bun 的优势在速度和工具链集成,适合新项目和对性能敏感的场景。但生态兼容性不如 Node.js,选择时需要根据项目情况判断。