ベストプラクティス
Honoは非常に柔軟です。好きなようにアプリを書くことができます。ただし、従うべきベストプラクティスがいくつかあります。
可能な場合は「コントローラー」を作成しない
可能であれば、"Ruby on Railsのようなコントローラー"を作成しないでください。
ts
// 🙁
// A RoR-like Controller
const booksList = (c: Context) => {
return c.json('list books')
}
app.get('/books', booksList)
この問題は型に関連しています。たとえば、パスパラメータは、複雑なジェネリクスを記述しないとコントローラー内で推論できません。
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のようなコントローラーを作成する必要はなく、パスの定義の直後にハンドラーを直接書く必要があります。
ts
// 😃
app.get('/books/:id', (c) => {
const id = c.req.param('id') // Can infer the path param
return c.json(`get ${id}`)
})
factory.createHandlers()
in hono/factory
それでもRoRのようなコントローラーを作成したい場合は、hono/factory
のfactory.createHandlers()
を使用します。これを使用すると、型推論が正常に機能します。
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)
大規模なアプリケーションの構築
app.route()
を使用して、"Ruby on Railsのようなコントローラー"を作成せずに、大規模なアプリケーションを構築します。
アプリケーションに/authors
と/books
のエンドポイントがあり、index.ts
からファイルを分離する場合は、authors.ts
と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
のパスにマウントします。
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
機能を使用する場合は、次のようにメソッドをチェーンする方法がより適切なソリューションです。
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;
この方法でこのルートを使用する場合、型を適切に推測できます。