This is the tiny developer documentation for Hono. # Start of Hono documentation # Hono Hono —— _**在日语中意为火焰🔥**_ —— 是一个基于 Web 标准构建的小巧、简单且极速的 Web 应用框架。 它能够运行在任意 JavaScript 运行时:Cloudflare Workers、Fastly Compute、Deno、Bun、Vercel、Netlify、AWS Lambda、Lambda@Edge,以及 Node.js。 快,而且不止于快。 ```ts twoslash import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => c.text('Hono!')) export default app ``` ## 快速上手 只需运行下列命令之一: ::: code-group ```sh [npm] npm create hono@latest ``` ```sh [yarn] yarn create hono ``` ```sh [pnpm] pnpm create hono@latest ``` ```sh [bun] bun create hono@latest ``` ```sh [deno] deno init --npm hono@latest ``` ::: ## 核心特性 - **极速性能** 🚀 —— `RegExpRouter` 路由器拥有极致性能,没有线性循环,真正的快。 - **轻量体积** 🪶 —— `hono/tiny` 预设压缩后小于 14kB。Hono 没有任何依赖,只使用 Web 标准。 - **多运行时** 🌍 —— 兼容 Cloudflare Workers、Fastly Compute、Deno、Bun、AWS Lambda 与 Node.js,同一份代码跑遍所有平台。 - **电池全配** 🔋 —— 内置中间件、可自定义中间件、第三方中间件与助手函数,开箱即用。 - **愉悦的开发体验** 😃 —— API 简洁清晰,对 TypeScript 提供一流支持,如今还拥抱了完备的类型系统。 ## 适用场景 Hono 是一个类似 Express 的纯后端 Web 应用框架,没有前端层。 它可以在 CDN 边缘运行,与中间件组合即可搭建更大的应用。 以下是几个典型案例: - 构建 Web API - 作为后端服务器的代理 - CDN 边缘的入口层 - 边缘计算应用 - 库或框架的基础服务器 - 全栈应用 ## 谁在使用 Hono? | 项目 | 平台 | 用途 | | --------------------------------------------------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------- | | [cdnjs](https://cdnjs.com) | Cloudflare Workers | 免费开源的 CDN 服务,_Hono 被用于提供 API 服务_。 | | [Cloudflare D1](https://www.cloudflare.com/developer-platform/d1/) | Cloudflare Workers | 无服务器 SQL 数据库,_Hono 被用于内部 API 服务_。 | | [Cloudflare Workers KV](https://www.cloudflare.com/developer-platform/workers-kv/) | Cloudflare Workers | 无服务器键值数据库,_Hono 被用于内部 API 服务_。 | | [BaseAI](https://baseai.dev) | 本地 AI 服务器 | 带有记忆功能的无服务器 AI Agent 流水线开源框架,_使用 Hono 搭建 API 服务器_。 | | [Unkey](https://unkey.dev) | Cloudflare Workers | 开源的 API 鉴权与授权平台,_Hono 被用于 API 服务器_。 | | [OpenStatus](https://openstatus.dev) | Bun | 开源的网站与 API 监控平台,_Hono 被用于 API 服务器_。 | | [Deno Benchmarks](https://deno.com/benchmarks) | Deno | 基于 V8 的安全 TypeScript 运行时,_Hono 用于基准测试_。 | | [Clerk](https://clerk.com) | Cloudflare Workers | 开源的用户管理平台,_Hono 被用于 API 服务器_。 | 还有以下团队也在生产环境中使用 Hono: - [Drivly](https://driv.ly/) - Cloudflare Workers - [repeat.dev](https://repeat.dev/) - Cloudflare Workers 想了解更多?请访问 [Who is using Hono in production?](https://github.com/orgs/honojs/discussions/1510)。 ## 一分钟体验 Hono 以下演示展示了如何使用 Hono 在 Cloudflare Workers 上创建应用。 ![演示动图:快速创建并迭代一个 Hono 应用](/images/sc.gif) ## 极速表现 **在 Cloudflare Workers 的各类路由器中,Hono 是最快的。** ``` Hono x 402,820 ops/sec ±4.78% (80 runs sampled) itty-router x 212,598 ops/sec ±3.11% (87 runs sampled) sunder x 297,036 ops/sec ±4.76% (77 runs sampled) worktop x 197,345 ops/sec ±2.40% (88 runs sampled) Fastest is Hono ✨ Done in 28.06s. ``` 查看 [更多基准测试](/docs/concepts/benchmarks)。 ## 轻量体积 **Hono 非常小。**在使用 `hono/tiny` 预设并压缩后,体积 **低于 14KB**。 拥有众多中间件和适配器,但只会在使用时才打包。作为对比,Express 的体积为 572KB。 ``` $ npx wrangler dev --minify ./src/index.ts ⛅️ wrangler 2.20.0 -------------------- ⬣ Listening at http://0.0.0.0:8787 - http://127.0.0.1:8787 - http://192.168.128.165:8787 Total Upload: 11.47 KiB / gzip: 4.34 KiB ``` ## 多款路由器 **Hono 提供多种路由器实现。** **RegExpRouter** 是 JavaScript 世界中最快的路由器。它在派发前先构建一个巨大的正则表达式,用以匹配路由。配合 **SmartRouter**,即可支持所有路由模式。 **LinearRouter** 能够极快地注册路由,适用于每次请求都会初始化应用的运行时。**PatternRouter** 则以简单的方式添加并匹配路由模式,让体积更小。 查看 [更多关于路由的信息](/docs/concepts/routers)。 ## Web 标准 得益于 **Web 标准**,Hono 可以运行在众多平台上。 - Cloudflare Workers - Cloudflare Pages - Fastly Compute - Deno - Bun - Vercel - AWS Lambda - Lambda@Edge - 以及更多 通过使用 [Node.js 适配器](https://github.com/honojs/node-server),Hono 也能在 Node.js 上运行。 查看 [更多关于 Web 标准的信息](/docs/concepts/web-standard)。 ## 中间件与助手 **Hono 拥有大量中间件与助手函数**,真正实现“写得更少,做得更多”。 开箱即用的中间件与助手包括: - [Basic Authentication](/docs/middleware/builtin/basic-auth) - [Bearer Authentication](/docs/middleware/builtin/bearer-auth) - [Body Limit](/docs/middleware/builtin/body-limit) - [Cache](/docs/middleware/builtin/cache) - [Compress](/docs/middleware/builtin/compress) - [Context Storage](/docs/middleware/builtin/context-storage) - [Cookie](/docs/helpers/cookie) - [CORS](/docs/middleware/builtin/cors) - [ETag](/docs/middleware/builtin/etag) - [html](/docs/helpers/html) - [JSX](/docs/guides/jsx) - [JWT Authentication](/docs/middleware/builtin/jwt) - [Logger](/docs/middleware/builtin/logger) - [Language](/docs/middleware/builtin/language) - [Pretty JSON](/docs/middleware/builtin/pretty-json) - [Secure Headers](/docs/middleware/builtin/secure-headers) - [SSG](/docs/helpers/ssg) - [Streaming](/docs/helpers/streaming) - [GraphQL Server](https://github.com/honojs/middleware/tree/main/packages/graphql-server) - [Firebase Authentication](https://github.com/honojs/middleware/tree/main/packages/firebase-auth) - [Sentry](https://github.com/honojs/middleware/tree/main/packages/sentry) - 以及更多! 例如,在 Hono 中仅需几行代码就能加入 ETag 与请求日志: ```ts import { Hono } from 'hono' import { etag } from 'hono/etag' import { logger } from 'hono/logger' const app = new Hono() app.use(etag(), logger()) ``` 查看 [更多关于中间件的信息](/docs/concepts/middleware)。 ## 开发者体验 Hono 带来令人愉悦的“**开发者体验**”。 得益于 `Context` 对象,可以轻松获取 Request/Response。 此外,Hono 采用 TypeScript 编写,自带“**类型**”。 例如,路径参数会被推断为字面量类型。 ![屏幕截图展示了当 URL 带有参数时,Hono 能正确推断字面量类型。路径 "/entry/:date/:id" 会让请求参数变成 "date" 或 "id"](/images/ss.png) 借助 Validator 与 Hono Client `hc`,可以启用 RPC 模式。 在该模式下,你可以继续使用自己喜爱的校验器(如 Zod),轻松在服务端与客户端之间共享 API 规范,从而构建类型安全的应用。 查看 [Hono Stacks](/docs/concepts/stacks)。 # 最佳实践 Hono 十分灵活,你可以按照自己的偏好编写应用。 不过,仍然有一些更值得遵循的最佳实践。 ## 尽量不要创建“控制器” 能不写“Ruby on Rails 风格的控制器”时,就别写。 ```ts // 🙁 // 类似 RoR 的控制器 const booksList = (c: Context) => { return c.json('list books') } app.get('/books', booksList) ``` 问题出在类型上。例如,如果不写复杂的泛型,控制器内部无法推断路径参数。 ```ts // 🙁 // 类似 RoR 的控制器 const bookPermalink = (c: Context) => { const id = c.req.param('id') // 无法推断路径参数 return c.json(`get ${id}`) } ``` 因此你完全没必要写 RoR 风格的控制器,直接在路径定义后编写处理函数即可。 ```ts // 😃 app.get('/books/:id', (c) => { const id = c.req.param('id') // 可以正确推断路径参数 return c.json(`get ${id}`) }) ``` ## 使用模式验证请求 如果需要验证请求,请使用模式验证器,而不要手写验证逻辑。 ```ts import { z } from 'zod' import { zValidator } from '@hono/zod-validator' app.post( '/auth', zValidator( 'json', z.object({ email: z.string().email(), password: z.string().min(8), }) ), async (c) => { const { email, password } = c.req.valid('json') return c.json({ email, password }) } ) ``` ## 在调用 `app.get()` 之前定义配置 这是来自 JavaScript 模块的最佳实践: 在调用函数之前先定义配置对象。 ```ts const route = { method: 'GET', path: '/', } app.get(route, (c) => c.text('Hello')) ``` ## 不要为了分组而重复使用 `app.route` 只有在需要为同一路径提供多个 HTTP 方法时,才应该使用 `app.route`。 如果只是想划分路由分组,就会显得多此一举。 ```ts const app = new Hono() const books = app.route('/books') books.get('/', (c) => c.json(['Hello'])) books.get('/:id', (c) => c.json({ id: c.req.param('id') })) ``` 在这种情况下就显得冗余了。直接写成下面这样能得到相同的效果。 ```ts app.get('/books', (c) => c.json(['Hello'])) app.get('/books/:id', (c) => c.json({ id: c.req.param('id') })) ``` ## 更倾向使用 `app.on` 而不是 `app.xxx` Hono 提供了 `app.on`,可以为同一路径定义多个 HTTP 方法。建议使用 `app.on`,而不是 `app.xxx`。 ```ts app.on(['GET', 'POST'], '/books', (c) => { return c.json(['Hello']) }) ``` ## 使用 `c.req.param()` 而非 `c.req.param['id']` 请使用函数形式的 `c.req.param()`,而不是访问器 `c.req.param['id']`,以避免触发 getter。 ```ts app.get('/books/:id', (c) => { const id = c.req.param('id') return c.json({ id }) }) ``` ## 用模板字符串拼接响应 拼接响应文本时,请使用模板字符串,而不是字符串相加。 ```ts app.get('/hello/:name', (c) => { const { name } = c.req.param() return c.text(`Hello ${name}!`) }) ``` ## 日志 使用 `console.log` 和 `console.error` 输出日志信息。 ```ts app.get('/hello', async (c) => { const start = Date.now() const res = await c.req.parseBody() const end = Date.now() console.log(`[${c.req.method}] ${c.req.path} - ${end - start}ms`) return c.json(res) }) ``` ## 用 `c.var` 复用逻辑 如果有重复使用的逻辑,可以通过 `c.set` 和 `c.var` 进行复用。 ```ts app.use('*', async (c, next) => { c.set('database', await getDatabase()) await next() }) app.get('/users', async (c) => { const db = c.var.database const users = await db.users.findMany() return c.json(users) }) ``` ## 等待 Response `Response` 只能读取一次。等待响应会消耗它。 ```ts app.get('/', async (c) => { const res = await fetch('https://example.com') const json = await res.json() return c.json(json) }) ``` # Create-hono 以下是 `create-hono` 支持的命令行选项。这个项目初始化工具会在你执行 `npm create hono@latest`、`npx create-hono@latest` 或 `pnpm create hono@latest` 时运行。 > [!NOTE] > **为什么需要这篇文档?** 安装与快速上手示例通常只展示最精简的 `npm create hono@latest my-app` 命令。其实 `create-hono` 提供了很多实用的参数,可以帮助你自动化并自定义项目创建过程(选择模板、跳过交互式提示、指定包管理器、使用本地缓存等)。 ## 传递参数 使用 `npm create`(或 `npx`)时,传给初始化脚本的参数必须放在 `--` 之后。`--` 后面的所有内容都会转发给初始化器。 ::: code-group ```sh [npm] # 将参数转发给 create-hono(npm 必须使用 `--`) npm create hono@latest my-app -- --template cloudflare-workers ``` ```sh [yarn] # "--template cloudflare-workers" 会选择 Cloudflare Workers 模板 yarn create hono my-app --template cloudflare-workers ``` ```sh [pnpm] # "--template cloudflare-workers" 会选择 Cloudflare Workers 模板 pnpm create hono@latest my-app --template cloudflare-workers ``` ```sh [bun] # "--template cloudflare-workers" 会选择 Cloudflare Workers 模板 bun create hono@latest my-app --template cloudflare-workers ``` ```sh [deno] # "--template cloudflare-workers" 会选择 Cloudflare Workers 模板 deno init --npm hono@latest my-app --template cloudflare-workers ``` ::: ## 常用参数 | 参数 | 说明 | 示例 | | :---------------------- | :------------------------------------------------------------------------------------------------ | :----------------------------- | | `--template