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

从语法层面看,两者都足够简洁。差异不在语法,而在于它们背后的运行时、部署模型和生态定位

维度FastAPIHono.js
语言PythonTypeScript / 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 的流式通信,逐步实现完整的对话管线。