Skip to content

最佳实践

¥Best Practices

Hono 非常灵活。你可以根据需要编写应用。但是,有更好的最佳实践可以遵循。

¥Hono is very flexible. You can write your app as you like. However, there are best practices that are better to follow.

尽可能不要制作 "控制器"

¥Don't make "Controllers" when possible

如果可能,你不应创建 "类似 Ruby on Rails 的控制器"。

¥When possible, you should not create "Ruby on Rails-like Controllers".

ts
// 🙁
// A RoR-like Controller
const booksList = (c: Context) => {
  return c.json('list books')
}

app.get('/books', booksList)

问题与类型有关。例如,如果不编写复杂的泛型,则无法在 Controller 中推断路径参数。

¥The issue is related to types. For example, the path parameter cannot be inferred in the Controller without writing complex generics.

ts
// 🙁
// A RoR-like Controller
const bookPermalink = (c: Context) => {
  const id = c.req.param('id') // Can't infer the path param
  return c.json(`get ${id}`)
}

因此,你不需要创建类似 RoR 的控制器,而应该在路径定义后直接编写处理程序。

¥Therefore, you don't need to create RoR-like controllers and should write handlers directly after path definitions.

ts
// 😃
app.get('/books/:id', (c) => {
  const id = c.req.param('id') // Can infer the path param
  return c.json(`get ${id}`)
})

hono/factory 中的 factory.createHandlers()

¥factory.createHandlers() in hono/factory

如果你仍想创建类似 RoR 的控制器,请在 hono/factory 中使用 factory.createHandlers()。如果你使用这种方法,类型推断将正常工作。

¥If you still want to create a RoR-like Controller, use factory.createHandlers() in hono/factory. If you use this, type inference will work correctly.

ts
import { createFactory } from 'hono/factory'
import { logger } from 'hono/logger'

// ...

// 😃
const factory = createFactory()

const middleware = factory.createMiddleware(async (c, next) => {
  c.set('foo', 'bar')
  await next()
})

const handlers = factory.createHandlers(logger(), middleware, (c) => {
  return c.json(c.var.foo)
})

app.get('/api', ...handlers)

构建更大的应用

¥Building a larger application

使用 app.route() 构建更大的应用而无需创建 "类似 Ruby on Rails 的控制器"。

¥Use app.route() to build a larger application without creating "Ruby on Rails-like Controllers".

如果你的应用有 /authors/books 端点,并且你希望将文件与 index.ts 分开,请创建 authors.tsbooks.ts

¥If your application has /authors and /books endpoints and you wish to separate files from index.ts, create authors.ts and books.ts.

ts
// authors.ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => c.json('list authors'))
app.post('/', (c) => c.json('create an author', 201))
app.get('/:id', (c) => c.json(`get ${c.req.param('id')}`))

export default app
ts
// books.ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => c.json('list books'))
app.post('/', (c) => c.json('create a book', 201))
app.get('/:id', (c) => c.json(`get ${c.req.param('id')}`))

export default app

然后,导入它们并将其与 app.route() 一起挂载在路径 /authors/books 上。

¥Then, import them and mount on the paths /authors and /books with app.route().

ts
// index.ts
import { Hono } from 'hono'
import authors from './authors'
import books from './books'

const app = new Hono()

// 😃
app.route('/authors', authors)
app.route('/books', books)

export default app

如果要使用 RPC 功能

¥If you want to use RPC features

上面的代码对于正常用例来说效果很好。但是,如果你想使用 RPC 功能,可以通过如下链接获取正确的类型。

¥The code above works well for normal use cases. However, if you want to use the RPC feature, you can get the correct type by chaining as follows.

ts
// authors.ts
import { Hono } from 'hono'

const app = new Hono()
  .get('/', (c) => c.json('list authors'))
  .post('/', (c) => c.json('create an author', 201))
  .get('/:id', (c) => c.json(`get ${c.req.param('id')}`))

export default app

如果你将 app 的类型传递给 hc,它将获得正确的类型。

¥If you pass the type of the app to hc, it will get the correct type.

ts
import app from './authors'
import { hc } from 'hono/client'

// 😃
const client = hc<typeof app>('http://localhost') // Typed correctly

有关更多详细信息,请参阅 RPC 页面

¥For more detailed information, please see the RPC page.

Hono v4.7 中文网 - 粤ICP备13048890号