Hono.js vs FastAPI
要点
- 在上一篇文章中,我们确定了边缘部署的技术方向,选择了 CloudFlare Workers 作为基础设施
- 先用一段最简单的代码感受两者的风格差异
- 1 边缘运行时兼容性——决定性差距
- 公平地说,FastAPI 在某些场景下仍然是更好的选择
- 回到 AI 伴侣项目的具体需求,我们的选型逻辑是这样的
内容
1. 为什么要单独讨论后端框架选型
在上一篇文章中,我们确定了边缘部署的技术方向,选择了 CloudFlare Workers 作为基础设施。但基础设施只是「地基」,在上面盖什么样的「房子」——也就是用什么框架来组织 API 代码——同样关键。
在我们的技术选型过程中,最终进入候选的是两个框架:Python 生态的 FastAPI 和 TypeScript 生态的 Hono.js。两者都以「轻量、高性能、现代」著称,但它们的设计哲学和适用场景完全不同。
坦率地说,当上一篇文章确定了 CloudFlare Workers 作为部署平台后,框架选型的结论已经基本明确了。但我们仍然需要这篇文章来回答一个更本质的问题:为什么我们不为了使用 FastAPI 而放弃边缘部署? 换句话说——FastAPI 的优势是否足以让我们改变部署策略?
2. 30 秒看懂两者的定位
先用一段最简单的代码感受两者的风格差异。
FastAPI:Python 生态的 API 框架
// app.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Message(BaseModel):
content: str
user_id: str
@app.post("/chat")
async def chat(msg: Message):
# 调用 LLM、检索记忆、组装回复...
return {"reply": f"收到: {msg.content}"}Hono.js:TypeScript 生态的轻量级 Web 框架
// index.ts
import { Hono } from 'hono'
const app = new Hono()
app.post('/chat', async (c) => {
const { content, user_id } = await c.req.json()
// 调用 LLM、检索记忆、组装回复...
return c.json({ reply: `收到: ${content}` })
})
export default app从语法层面看,两者都足够简洁。差异不在语法,而在于它们背后的运行时、部署模型和生态定位。
| 维度 | FastAPI | Hono.js |
|---|---|---|
| 语言 | Python | TypeScript / JavaScript |
| 运行时 | CPython / uvicorn | 任意 JS 运行时(Node、Deno、Bun、Workers) |
| 定位 | 全功能 API 框架 | 超轻量 Web 框架 |
| 包体积 | ~30MB(含依赖) | ~14KB(无依赖) |
| 首个 stable 版本 | 2018 年 | 2022 年 |
3. 五个维度的深度对比
3.1 边缘运行时兼容性——决定性差距
这是最核心的区别,也是我们选型的第一决策因素。
FastAPI 需要完整的 Python 运行时。 它依赖 CPython 解释器、uvicorn ASGI 服务器、以及一系列 C 扩展(如 pydantic 的 Rust 编译后端)。这意味着它只能跑在传统服务器或容器中——AWS EC2、Docker、Lambda(冷启动慢)。
CloudFlare Workers 无法运行 FastAPI。 虽然 Workers 已经通过 Pyodide(WASM 编译的 CPython)提供了实验性的 Python 支持,但它仍处于早期阶段,不支持 FastAPI 所依赖的 ASGI 服务器和 C 扩展生态(uvicorn、pydantic v2 的 Rust 后端等)。在可预见的未来,FastAPI 无法在边缘运行时中运行。
Hono.js 从设计之初就考虑了多运行时兼容:
// index.ts
// CloudFlare Workers
export default app
// Node.js
import { serve } from '@hono/node-server'
serve(app)
// Deno
Deno.serve(app.fetch)
// Bun
export default app同一份代码,零修改运行在四种运行时上。这不是锦上添花,而是直接决定了你的部署选项。
如果你选了 FastAPI,就等于放弃了边缘部署——而上一篇文章我们已经论证了,边缘部署对 AI 伴侣的实时对话体验是决定性的。
3.2 冷启动与运行时性能
即使不考虑边缘部署,只看传统 Serverless 场景(AWS Lambda、Vercel Functions),两者的冷启动差距也非常显著。
| 指标 | FastAPI(Lambda) | Hono.js(Workers) |
|---|---|---|
| 冷启动时间 | 300-3000ms | < 5ms |
| 运行时开销 | ~50MB 内存起步 | < 1MB |
| 并发模型 | 单进程异步(GIL 限制 CPU 密集任务) | V8 Isolate(轻量隔离) |
NOTE
需要说明的是,这里的冷启动差距主要来自运行时平台(Lambda vs Workers),而不完全是框架本身的差异。但这恰恰印证了选型的关键点:框架和平台是绑定的——选 FastAPI 就意味着选 Python 运行时,就意味着无法使用 Workers 这类轻量级边缘平台。
FastAPI 的冷启动慢,根本原因是 Python 解释器 + 依赖包的加载。每次冷启动都要重新加载整个 Python 运行时和所有 import 的模块。在 Lambda 中,如果你依赖了 numpy、pydantic v2(Rust 编译)等库,冷启动轻松突破 2 秒。
Hono.js 在 Workers 上的冷启动几乎可以忽略。V8 Isolate 的启动开销极低,整个框架只有 14KB,没有依赖需要加载。
对 AI 伴侣来说,冷启动意味着什么?用户沉默了几分钟没发消息,再发一条时,Lambda 实例已经被回收了。 下一条消息的首字节时间 = 冷启动 + 处理时间 + LLM 推理。如果冷启动吃掉 2 秒,用户体验直接崩溃。
3.3 前后端技术栈统一
AI 伴侣项目的前端是 React / Next.js,全部使用 TypeScript。如果后端也使用 TypeScript:
类型共享。 前后端可以直接共享接口类型定义,无需手动同步、无需生成 OpenAPI schema 再生成客户端代码。
// types.ts
// 这个类型定义,前端和后端直接 import 同一份文件
export interface ChatRequest {
content: string
user_id: string
session_id: string
}
export interface ChatResponse {
reply: string
emotion: string
memories_used: number
}工具链统一。 同一套 ESLint、Prettier / Biome、tsconfig、包管理器(yarn)。不需要在项目中同时维护 Python 和 TypeScript 两套工具链。
认知负担低。 团队成员(尤其是前端开发者)不需要在两种语言之间频繁切换。AI 伴侣项目的服务端逻辑主要是 API 编排(调 LLM、查数据库、拼 Prompt),并不需要 Python 在数据科学领域的优势。
RPC 类型安全调用。 Hono.js 内置了 RPC 客户端,可以让前端调用后端 API 时获得端到端的类型推断——连请求参数和响应类型都是自动推导的,无需手动定义共享类型。
// server.ts
// 后端:定义路由
const route = app.post('/chat',
zValidator('json', chatSchema),
async (c) => {
const body = c.req.valid('json')
return c.json({ reply: '...', emotion: 'happy' })
}
)
export type AppType = typeof route// client.ts
// 前端:自动推断请求和响应类型,无需任何手动定义
import { hc } from 'hono/client'
import type { AppType } from '../server'
const client = hc<AppType>('/api')
// res 的类型自动推断为 { reply: string, emotion: string }
const res = await client.chat.$post({ json: { content: '你好' } })这比手动共享 interface 强大得多。前端调用 API 就像调用本地函数一样,参数写错了 TypeScript 编译器会直接报错。这是 Hono.js 在类型安全维度上的杀手级特性。
FastAPI 在这个维度上的劣势是结构性的。即使 FastAPI 本身很优秀,但它会在项目中引入 Python 运行时、pip/poetry 依赖管理、Python 类型系统(与 TypeScript 不互通)、以及额外的部署流水线。
3.4 CloudFlare 生态集成
选择了 CloudFlare Workers 作为基础设施后,框架与平台的集成深度直接影响开发效率。
Hono.js 是 CloudFlare 生态的一等公民。它对 Workers 的 Bindings 有原生支持:
// index.ts
import { Hono } from 'hono'
type Bindings = {
KV: KVNamespace // 键值存储
DB: D1Database // SQL 数据库
VECTORIZE: VectorizeIndex // 向量数据库
AI: Ai // Workers AI 推理
}
const app = new Hono<{ Bindings: Bindings }>()
app.post('/chat', async (c) => {
// 直接通过 c.env 访问所有 CloudFlare 服务,完整的类型提示
const emotion = await c.env.KV.get(`emotion:${userId}`, 'json')
const memories = await c.env.DB.prepare('SELECT ...').all()
const embedding = await c.env.AI.run('@cf/baai/bge-base-en-v1.5', { text: query })
const similar = await c.env.VECTORIZE.query(embedding.data[0], { topK: 5 })
return c.json({ /* ... */ })
})KV、D1、Vectorize、Workers AI——前面几篇文章介绍的所有存储和推理服务,都可以通过 c.env 直接访问,带完整的 TypeScript 类型提示。
FastAPI 无法直接访问这些服务。你需要通过 REST API 从外部调用 CloudFlare 的服务,引入额外的网络开销和复杂度。这就像住在酒店里,但每次用电都要跑到隔壁楼按开关。
3.5 中间件与 API 编排能力
AI 伴侣的后端不需要复杂的业务逻辑,但需要精细的请求处理管线:安全检查 → 身份验证 → 记忆检索 → Prompt 组装 → LLM 调用 → 记忆写回 → 响应返回。
Hono.js 的中间件模型简洁有力:
// index.ts
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import { timing } from 'hono/timing'
const app = new Hono()
// 内置中间件
app.use('*', cors())
app.use('*', logger())
app.use('*', timing())
// 自定义中间件:安全检查
app.use('/chat/*', async (c, next) => {
const content = await c.req.text()
if (containsUnsafeContent(content)) {
return c.json({ error: '内容不合规' }, 403)
}
await next()
})
// 自定义中间件:身份验证
app.use('/chat/*', async (c, next) => {
const token = c.req.header('Authorization')
const user = await verifyToken(token)
c.set('user', user)
await next()
})
// 路由处理
app.post('/chat/message', async (c) => {
const user = c.get('user')
// 已经通过了安全检查和身份验证
// ...
})FastAPI 也有中间件和依赖注入系统,而且 FastAPI 的依赖注入在复杂场景下更强大。但对 AI 伴侣这种"编排型"后端来说,Hono.js 的洋葱模型已经完全够用,而且代码更直观。
4. FastAPI 的优势在哪
公平地说,FastAPI 在某些场景下仍然是更好的选择:
数据科学与机器学习。 如果你需要在服务端做数据处理(pandas、numpy)、模型训练或推理(PyTorch、transformers),Python 生态无可替代。但 AI 伴侣的服务端不做推理,只做调度。
自动文档生成。 FastAPI 基于 OpenAPI 规范自动生成交互式 API 文档(Swagger UI / ReDoc)。如果你的 API 需要对外暴露给第三方开发者,这是一个很强的能力。Hono.js 虽然也支持 OpenAPI(通过 zod-openapi),但成熟度不如 FastAPI。
复杂的依赖注入。 FastAPI 的 Depends() 系统可以构建复杂的依赖树,自动解析和注入。对于大型单体应用,这种能力很有价值。
Python 团队。 如果你的团队全是 Python 工程师,强行用 TypeScript 写后端反而增加成本。技术选型必须考虑团队实际情况。
5. 选型决策总结
回到 AI 伴侣项目的具体需求,我们的选型逻辑是这样的:
| 需求 | FastAPI 能否满足 | Hono.js 能否满足 |
|---|---|---|
| 部署在 CloudFlare Workers | 不能 | 原生支持 |
| 冷启动 < 10ms | 不能 | < 5ms |
| 前后端 TypeScript 类型共享 | 不能 | 天然支持 |
| 直接访问 KV / D1 / Vectorize | 需要外部 API 调用 | 通过 Bindings 原生访问 |
| 流式 SSE 响应(LLM 输出) | 支持(需配置) | 原生支持 |
| 轻量级 API 编排 | 支持(偏重) | 完美匹配 |
| 数据科学 / ML 推理 | 强项 | 不适用 |
| 自动 API 文档 | 内置(强) | 社区方案(中) |
最终结论:FastAPI 是一个优秀的框架,但它不适合我们的场景。
我们的后端不做推理,不做数据处理,不需要 Python 生态的核心优势。我们需要的是一个能跑在边缘、冷启动极快、与 CloudFlare 生态深度集成、并且与前端共享类型系统的轻量框架。在这个需求矩阵下,Hono.js 是唯一的选择,而不仅仅是"更好的选择"。
在后续的文章中,我们将基于 Hono.js + CloudFlare Workers 开始搭建 AI 伴侣的后端服务,从路由设计、中间件编排、到与 LLM 的流式通信,逐步实现完整的对话管线。