Hono 前后端分离系列 10:部署和生产架构
前后端分离项目最后一定会回到一个问题:
本地跑通只是第一步。
真正上线时,你要考虑:
1 2 3 4 5 6 7 8
| 前端放哪里? API 放哪里? 域名怎么分? 环境变量怎么管? 跨域怎么配? 日志怎么看? 数据库在哪里? 回滚怎么做?
|
Hono 的优势是多运行时。
同一套核心 API 代码,可以跑在 Cloudflare Workers、Node.js、Bun、Deno、Vercel、Netlify 等环境。不同部署方式没有绝对好坏,关键是和项目形态匹配。
一、最推荐的轻量组合
如果是中小型前后端分离项目,我很喜欢这个组合:
1 2 3 4 5
| 前端:Cloudflare Pages 后端:Cloudflare Workers + Hono 数据库:D1 / 外部 Postgres 文件:R2 缓存:KV / Cache API
|
优点是:
- 部署简单
- 全球边缘节点
- 不用维护服务器
- Hono 和 Workers 适配自然
- 小项目成本很低
Hono 官方 Cloudflare Workers 文档也强调,可以用 Wrangler 本地开发和发布,并通过 c.env 访问 Workers bindings。
如果你已经在用 Cloudflare,这套组合非常顺。
二、域名怎么设计
常见两种方式。
第一种,前端和 API 分不同子域名:
1 2
| https://app.example.com https://api.example.com
|
优点是边界清楚,部署独立。
缺点是要处理 CORS。
第二种,同域名不同路径:
1 2
| https://example.com https://example.com/api
|
优点是跨域问题少,cookie 更好处理。
缺点是路由、网关或平台配置要更小心。
如果你是纯 SPA + API,我通常会选:
1
| app.example.com + api.example.com
|
如果你强依赖 cookie 登录,或者想减少跨域复杂度,可以考虑同域路径。
三、Cloudflare Workers 部署
一个基础 wrangler.jsonc:
1 2 3 4 5 6 7 8
| { "name": "hono-api", "main": "src/index.ts", "compatibility_date": "2026-06-23", "vars": { "CORS_ORIGIN": "https://app.example.com" } }
|
Hono 入口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { Hono } from 'hono'
type Bindings = { CORS_ORIGIN: string JWT_SECRET: string }
const app = new Hono<{ Bindings: Bindings }>()
app.get('/api/health', (c) => { return c.json({ ok: true }) })
export default app
|
部署:
敏感信息不要写到 vars 里提交。
用 Wrangler secret:
1
| pnpm exec wrangler secret put JWT_SECRET
|
四、Node.js 部署
如果你需要传统服务器,也可以用 Node.js。
入口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { serve } from '@hono/node-server' import { Hono } from 'hono'
const app = new Hono()
app.get('/api/health', (c) => c.json({ ok: true }))
const server = serve({ fetch: app.fetch, port: Number(process.env.PORT ?? 3000), })
process.on('SIGTERM', () => { server.close() })
|
适合 Node.js 的场景:
- 需要长连接或特殊 Node 能力
- 已有服务器和运维体系
- 使用传统数据库连接池
- 要跑在 Docker / Kubernetes
适合 Workers 的场景:
- 请求响应型 API
- Serverless 优先
- 希望少运维
- 接近用户的边缘服务
- 和 D1、KV、R2 集成
不要为了“高级”强行选边缘,也不要因为习惯就永远选服务器。
五、环境变量分层
至少分三套:
1 2 3
| local staging production
|
常见变量:
1 2 3 4 5
| CORS_ORIGIN JWT_SECRET DATABASE_URL LOG_LEVEL FEATURE_FLAGS
|
前端也有自己的变量:
不要让前端构建时拿到后端 secret。
前端环境变量会被打进浏览器包里。任何 VITE_ 开头的变量,都应该默认视为公开信息。
六、生产中间件清单
上线前,Hono API 至少考虑这些中间件:
1 2 3 4 5 6 7 8 9
| CORS secureHeaders requestId logger bodyLimit timeout JWT / Bearer Auth onError notFound
|
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import { cors } from 'hono/cors' import { secureHeaders } from 'hono/secure-headers' import { requestId } from 'hono/request-id' import { bodyLimit } from 'hono/body-limit'
app.use('*', requestId()) app.use('*', secureHeaders()) app.use('/api/*', async (c, next) => { const corsHandler = cors({ origin: c.env.CORS_ORIGIN, })
return corsHandler(c, next) }) app.use('/api/*', bodyLimit({ maxSize: 1024 * 1024 }))
app.notFound((c) => { return c.json({ error: { code: 'NOT_FOUND', message: '接口不存在', }, }, 404) })
app.onError((err, c) => { console.error(err) return c.json({ error: { code: 'INTERNAL_SERVER_ERROR', message: '服务器内部错误', }, }, 500) })
|
注意 c.env.CORS_ORIGIN 只能在请求上下文里读取,所以这里用一层 middleware 包起来,根据当前环境创建 cors handler。
七、发布前检查清单
上线前我会检查:
1 2 3 4 5 6 7 8 9 10
| 生产 CORS origin 是否正确 JWT_SECRET 是否为强随机值 接口错误是否不返回 stack 请求体大小是否有限制 数据库迁移是否执行 前端 API 地址是否指向生产 日志里是否有 requestId 健康检查是否可访问 404 和 500 是否统一 回滚方式是否明确
|
这张清单比“能部署成功”更重要。
能部署成功只说明平台接受了你的代码。
能稳定运行,才说明你准备好了生产环境。
八、最后的建议
Hono 的部署选择很多。
不要从平台开始选,要从项目需求开始选:
1 2 3 4 5
| 轻量 API、低运维、全球访问:Cloudflare Workers 传统服务、连接池、长任务:Node.js 前端静态资源:Pages / Vercel / Netlify 同域体验优先:前端和 API 走同域路径 边界清楚优先:app 子域 + api 子域
|
前后端分离不是部署成两个地址就完了。
真正的生产架构,要把域名、环境变量、安全、日志、数据库、回滚都想清楚。
Hono 让 API 层足够轻,但生产环境不能轻率。
参考资料