22.03-Bun部署
要点
- Bun 是一个高性能的 JS 运行时,内置打包器和包管理器
- Hono 原生支持 Bun,不需要额外适配器
- Bun 的优势:启动快、内存占用低、内置 SQLite
- 部署方式和 Node.js 类似,但可以用更少的工具链
内容
1. Bun 是什么
Bun 是一个用 Zig 写的 JS 运行时,目标是替代 Node.js,提供更快的速度和更好的开发体验。
| 特性 | Node.js | Bun |
|---|---|---|
| 引擎 | V8 | JavaScriptCore(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.tsBun 原生支持 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.jsbun 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.js | Bun |
|---|---|---|
| TypeScript 支持 | 需要编译或 tsx | 原生支持 |
| 启动速度 | 较慢 | 快 |
| 内存占用 | 较高 | 较低 |
| 包管理器 | npm/pnpm/yarn | 内置 bun |
| 打包器 | 需要 esbuild/webpack | 内置 bun build |
| SQLite | 需要 better-sqlite3 | 内置 bun:sqlite |
| 生态兼容性 | 最好(npm 生态) | 大部分兼容,少数包有问题 |
Bun 的优势在速度和工具链集成度。劣势在生态兼容性——虽然大部分 npm 包都能用,但偶尔会遇到不兼容的情况。
8. 适用场景
Bun 适合这些场景:
- 新项目:不需要兼容旧代码,可以享受 Bun 的全部优势
- 性能敏感:启动速度和内存占用比 Node.js 好
- 小型后端:内置 SQLite + 内置打包,工具链简单
- 脚本和 CLI:Bun 跑脚本比 Node.js 快
不适合:
- 依赖大量 Node.js 原生模块:部分原生模块不兼容
- 需要极致稳定性:Bun 还在快速迭代,API 可能有变化
- 企业级项目:Node.js 的生态和社区支持更成熟
9. 小结
Bun 部署的核心:
- Hono 原生支持 Bun,不需要适配器
- 可以直接跑 TypeScript,不需要先编译
bun build --compile可以编译成独立可执行文件- 内置 SQLite,小型项目不需要外部数据库
- 进程管理用 PM2(支持 Bun 作为解释器)
Bun 的优势在速度和工具链集成,适合新项目和对性能敏感的场景。但生态兼容性不如 Node.js,选择时需要根据项目情况判断。