mcpField
H
hono

hono

github.com/sickn33开发49.1k60 次安装今天更新
代码仓库

关于 hono

Hono 是基于 Web 标准的轻量 Web 框架,面向构建边缘 API、BFF 和全栈应用的开发者。它支持多种运行时,并提供路由、中间件与类型化 RPC 客户端。

主要功能

  1. 01基于 Web 标准的请求与响应
  2. 02适配多种 JavaScript 运行时
  3. 03路由与中间件系统
  4. 04内置 JSX 支持
  5. 05类型化 RPC 客户端

适用场景

  1. 01构建边缘 REST 或 RPC API
  2. 02为 Bun 或 Node.js 创建类型安全服务
  3. 03开发低延迟 BFF
  4. 04在前后端共享类型化路由

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill hono

安装后在 Claude Code 中输入/hono确认已加载。

详细介绍

Hono Web Framework

概述

Hono(炎,在日语中意为“火焰”)是一款基于 Web 标准(Request/Response/fetch)构建的小巧、超快速 Web 框架。它可在任何环境中运行:Cloudflare Workers、Deno Deploy、Bun、Node.js、AWS Lambda,以及任何兼容 WinterCG 的运行时,而且代码完全相同。Hono 的路由器是目前速度最快的路由器之一,其中间件系统、内置 JSX 支持和 RPC 客户端,使其成为边缘 API、BFF 和轻量级全栈应用的理想选择。

何时使用此技能

  • 构建用于边缘部署(Cloudflare Workers、Deno Deploy)的 REST 或 RPC API 时
  • 需要用于 Bun 或 Node.js 的精简且类型安全的服务端框架时
  • 构建对延迟要求较低的前端后端服务(BFF)层时
  • 从 Express 迁移,但希望获得更好的 TypeScript 支持和边缘兼容性时
  • 用户询问 Hono 路由、中间件、c.req、c.json 或 hc() RPC 客户端时

工作原理

第 1 步:项目设置

Cloudflare Workers(推荐用于边缘部署):

npm create hono@latest my-api
# Select: cloudflare-workers
cd my-api
npm install
npm run dev    # Wrangler local dev
npm run deploy # Deploy to Cloudflare

Bun / Node.js:

mkdir my-api && cd my-api
bun init
bun add hono
// src/index.ts (Bun)
import { Hono } from 'hono';

const app = new Hono();

app.get('/', c => c.text('Hello Hono!'));

export default {
  port: 3000,
  fetch: app.fetch,
};
第 2 步:路由
import { Hono } from 'hono';

const app = new Hono();

// Basic methods
app.get('/posts', c => c.json({ posts: [] }));
app.post('/posts', c => c.json({ created: true }, 201));
app.put('/posts/:id', c => c.json({ updated: true }));
app.delete('/posts/:id', c => c.json({ deleted: true }));

// Route params and query strings
app.get('/posts/:id', async c => {
  const id = c.req.param('id');
  const format = c.req.query('format') ?? 'json';
  return c.json({ id, format });
});

// Wildcard
app.get('/static/*', c => c.text('static file'));

export default app;

链式路由:

app
  .get('/users', listUsers)
  .post('/users', createUser)
  .get('/users/:id', getUser)
  .patch('/users/:id', updateUser)
  .delete('/users/:id', deleteUser);
第 3 步:中间件

Hono 中间件的工作方式与 fetch 拦截器完全相同——在处理程序执行前后运行:

import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { cors } from 'hono/cors';
import { bearerAuth } from 'hono/bearer-auth';

const app = new Hono<{ Variables: { requestId: string } }>();

// Built-in middleware
app.use('*', logger());
app.use('/api/*', cors({ origin: 'https://myapp.com' }));
app.use('/api/admin/*', bearerAuth({ token: process.env.API_TOKEN! }));

// Custom middleware
app.use('*', async (c, next) => {
  c.set('requestId', crypto.randomUUID());
  await next();
  c.header('X-Request-Id', c.get('requestId'));
});

可用的内置中间件: logger、cors、csrf、etag、cache、basicAuth、bearerAuth、jwt、compress、bodyLimit、timeout、prettyJSON、secureHeaders。

以下内容列出的是可选的解析/响应方法,并非按顺序执行的处理程序:根据 Content-Type 解析一次请求正文,在运行时进行校验,并且只返回一个响应。从 hono/cookie 导入 getCookie。JSON 泛型不会校验输入。对 D1 和发布变更进行校验/授权,限制正文大小,只返回获准公开的字段,并处理错误。Bearer/JWT 代码片段需要配置强密钥和算法,并根据部署环境检查声明/过期时间/受众/签发者;请核实所安装 Hono 主版本对应的准确 API。在 Workers 中使用 c.env 绑定,而不要采用 Node 的 process.env 示例。CORS 不等于授权;脚手架提供的部署命令会发布实际资源,因此必须使用经过批准的账号/路由。

第 4 步:请求和响应辅助方法
app.post('/submit', async c => {
  // Parse body
  const body = await c.req.json<{ name: string; email: string }>();
  const form = await c.req.formData();
  const text = await c.req.text();

  // Headers and cookies
  const auth = c.req.header('authorization');
  const token = getCookie(c, 'session');

  // Responses
  return c.json({ ok: true });                        // JSON
  return c.text('hello');                             // plain text
  return c.html('<h1>Hello</h1>');                    // HTML
  return c.redirect('/dashboard', 302);              // redirect
  return new Response(stream, { status: 200 });       // raw Response
});
第 5 步:Zod 校验器中间件
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';

const createPostSchema = z.object({
  title: z.string().min(1).max(200),
  body: z.string().min(1),
  tags: z.array(z.string()).default([]),
});

app.post(
  '/posts',
  zValidator('json', createPostSchema),
  async c => {
    const data = c.req.valid('json'); // fully typed
    const post = await db.post.create({ data });
    return c.json(post, 201);
  }
);
第 6 步:路由组和应用组合
// src/routes/posts.ts
import { Hono } from 'hono';

const posts = new Hono();

posts.get('/', async c => { /* list posts */ });
posts.post('/', async c => { /* create post */ });
posts.get('/:id', async c => { /* get post */ });

export default posts;
// src/index.ts
import { Hono } from 'hono';
import posts from './routes/posts';
import users from './routes/users';

const app = new Hono().basePath('/api');

app.route('/posts', posts);
app.route('/users', users);

export default app;
第 7 步:RPC 客户端(端到端类型安全)

Hono 的 RPC 模式会导出路由类型,供 hc 客户端使用——类似于 tRPC,但采用 fetch 约定:

// server: src/routes/posts.ts
import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';

const posts = new Hono()
  .get('/', c => c.json({ posts: [{ id: '1', title: 'Hello' }] }))
  .post(
    '/',
    zValidator('json', z.object({ title: z.string() })),
    async c => {
      const { title } = c.req.valid('json');
      return c.json({ id: '2', title }, 201);
    }
  );

export default posts;
export type PostsType = typeof posts;
// client: src/client.ts
import { hc } from 'hono/client';
import type { PostsType } from '../server/routes/posts';

const client = hc<PostsType>('/api/posts');

// Fully typed — autocomplete on routes, params, and responses
const response = await client.$get();
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { posts } = await response.json();
const created = await client.$post({ json: { title: 'New Post' } });
const newPost = await created.json();

示例

示例 1:JWT 身份验证中间件
import { Hono } from 'hono';
import { jwt, sign } from 'hono/jwt';

const app = new Hono();
const SECRET = process.env.JWT_SECRET!;

app.post('/login', async c => {
  const { email, password } = await c.req.json();
  const user = await validateUser(email, password);
  if (!user) return c.json({ error: 'Invalid credentials' }, 401);

  const token = await sign({ sub: user.id, exp: Math.floor(Date.now() / 1000) + 3600 }, SECRET);
  return c.json({ token });
});

app.use('/api/*', jwt({ secret: SECRET }));
app.get('/api/me', async c => {
  const payload = c.get('jwtPayload');
  const user = await getUserById(payload.sub);
  return c.json(user);
});

export default app;
示例 2:使用 D1 数据库的 Cloudflare Workers
// src/index.ts
import { Hono } from 'hono';

type Bindings = {
  DB: D1Database;
  API_TOKEN: string;
};

const app = new Hono<{ Bindings: Bindings }>();

app.get('/users', async c => {
  const { results } = await c.env.DB.prepare('SELECT * FROM users LIMIT 50').all();
  return c.json(results);
});

app.post('/users', async c => {
  const { name, email } = await c.req.json();
  await c.env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
    .bind(name, email)
    .run();
  return c.json({ created: true }, 201);
});

export default app;
示例 3:流式响应
import { stream, streamText } from 'hono/streaming';

app.get('/stream', c =>
  streamText(c, async stream => {
    for (const chunk of ['Hello', ' ', 'World']) {
      await stream.write(chunk);
      await stream.sleep(100);
    }
  })
);

最佳实践

  • ✅ 使用路由组(子应用),将处理程序放在不同文件中——app.route('/users', usersRouter)
  • ✅ 使用 zValidator 校验所有请求正文、查询参数和路径参数
  • ✅ 使用 Bindings 泛型为 Cloudflare Workers 绑定指定类型:new Hono<{ Bindings: Env }>()
  • ✅ 前端和后端位于同一代码仓库时,使用 RPC 客户端(hc)
  • ✅ 优先使用 c.json()/c.text(),而不是 new Response(),让代码更简洁
  • ❌ 如果需要边缘可移植性,请勿使用 Node.js 专用 API(fs、path、process)
  • ❌ 不要添加沉重的依赖项——Hono 的优势在于其在边缘运行时中占用空间极小
  • ❌ 不要跳过中间件类型定义——使用泛型(Variables、Bindings),确保 c.get() 类型安全

安全与防护说明

  • 使用请求中的数据前,务必先通过 zValidator 验证输入。
  • 提供 HTML/表单时,在变更端点上使用 Hono 内置的 csrf 中间件。
  • 对于 Cloudflare Workers,将非机密配置存储在 wrangler.toml 的 [vars] 中,并使用 wrangler secret put 存储机密——切勿将其硬编码到源代码中。
  • 使用 bearerAuth 或 jwt 时,确保在服务端验证令牌——不要信任客户端提供的用户 ID。
  • 使用 Cloudflare Rate Limiting 或自定义中间件,对敏感端点(身份验证、密码重置)进行速率限制。

常见问题

  • 问题: 处理程序返回 undefined——响应为空 解决方案: 处理程序务必 return 一个响应:使用 return c.json(...),而不只是 c.json(...)。

  • 问题: 响应发送后才运行中间件 解决方案: 在响应后的逻辑之前调用 await next();Hono 会在响应沿调用链返回时运行 next() 之后的代码。

  • 问题: 在 Node.js 上 c.env 未定义 解决方案: Cloudflare 的 env 绑定仅存在于 Workers 中。在 Node.js 上使用 process.env。

  • 问题: 路由未匹配——收到 404 解决方案: 检查 app.route('/prefix', subRouter) 使用的前缀是否与客户端调用的前缀相同。子路由不应在自身路由中重复此前缀。

相关技能

  • @cloudflare-workers-expert — 深入了解 Cloudflare Workers 平台特性
  • @trpc-fullstack — TypeScript 全栈应用的另一种 RPC 方案
  • @zod-validation-expert — 使用 @hono/zod-validator 时的详细 Zod 模式
  • @nodejs-backend-patterns — 需要 Node.js 专用后端(而非边缘端)时使用

限制

  • 仅当任务明确符合上述范围时,才使用此技能。
  • 不要将输出视为环境特定验证、测试或专家审查的替代品。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止并请求澄清。

评论

支持 Markdown