Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Next.jsでもHonoを使ってOpenAPIの支援を受けられるようにする #honoconf

Avatar for Azuki-bar Azuki-bar
October 18, 2025
550

Next.jsでもHonoを使ってOpenAPIの支援を受けられるようにする #honoconf

Avatar for Azuki-bar

Azuki-bar

October 18, 2025
Tweet

Transcript

  1. 5

  2. 6

  3. 類似テーマの2名 - フロントエンド主体で進めるHono×zod-openapiのスキー マ駆動開発 - スキーマをもとにモックを作成 - スキーマ駆動開発における開発プロセス - スキーマ駆動で、Zod

    OpenAPI Honoによる、API開発す るために、Hono Takibiというライブラリを作っている - OpenAPIのスキーマからhono/zod-openapiを作るHono Takibiの話 - 話すテーマとは逆のアプローチ 7
  4. ユーザーから見えるのは Next.jsアプリのみ - Next.jsアプリがユーザーから見えるUIを提供 - App Router - 表示するデータの取得 -

    Server Functionsでのデータ更新 - ドメイン固有の処理はNext.jsアプリ内に定義 - DBへ保存するJSONカラムのスキーマ 13
  5. 実装あるある - 新機能の追加に向けAPIを実装 - APIを使う側と提供する側で分かれて実装 - 結合したら400 Bad Request -

    入出力値スキーマの変更追従漏れ - あとから値が不足していることに気がつく 16
  6. APIの仕様を書いて共有 - 仕様を合意してから作る - 「/api/ _/interview に ?id=foo を付けてGETをすると データが取れます」

    - 「保存するときのBodyはこれでいきます」 - @valibot/json-schema で吐いたJSON Schemaを貼る - 最初のほうはなんとかなる 17
  7. 崩壊 - 実装を進めると過不足に気がつく - 取得するリソースを絞りたい - バルクで取得したい - 直す -

    (ここでドキュメント・実装の追従が漏れる) - 突然壊れる - さっきまで使えていたエンドポイントが400を返す 18
  8. Dynamic Route Segments - パスにidなどが含まれるURLを処理する仕組み - 例)GET /api/foo/:slug/list - ハンドラ内でURLの値を取得できる

    - 例) slug - []で囲うと動的になる - 例)api/foo/[slug]/list/route.ts で/api/foo/1/list な どの処理ができる 24
  9. 2つのCatch-all - Catch-all - /api/foo/[...slug]/route.tsで以下にマッチ - /api/foo/1, /api/foo/1/2/3 - Optional

    Catch-all - /api/foo/[[...slug]]/route.tsで以下にマッチ - /api/foo/1, /api/foo/1/2/3, /api/foo - あとで出てきます 26
  10. 2つのCatch-all - Catch-all - /api/foo/[...slug]/route.tsで以下にマッチ - /api/foo/1, /api/foo/1/2/3 - Optional

    Catch-all - /api/foo/[[...slug]]/route.tsで以下にマッチ - /api/foo/1, /api/foo/1/2/3, /api/foo ←にマッチするのが Optional Catch-all - あとで出てきます 27
  11. Next.jsルーティングまとめ - 基本はファイルベース - []で囲うとハンドラで値が取れる - 例) /api/foo/[slug]/list - [...slug]のように3点始まりだとCatch-all

    - [[...slug]]のように[[]]で囲うとOptional Catch-all - ()で囲うとパスに表れないグループができる - Route Groups 29
  12. Zod, Valibotなどのスキーマライブラ リ - スキーマを定義し検査するライブラリ - Zod, Valibot, ArkType, …

    - TypeScriptだと値に型がついてお得 import * as v from 'valibot'; const inputSchema = v.object({ id: v.string() }) v.parse(inputSchema, await req.json()) 33
  13. Honoのハンドラどこに置く - (復習)[[...foo]]/route.tsで全てのリクエス トを扱える - Optional Catch-all Segments - Route

    Groupsで関心を分けたい - Next.jsで処理されるハンドラとHonoで処理されるハン ドラ 38
  14. 実装例 // app/api/(hono)/[[...slug]]/route.tsに以下のファイルを配置 import { Hono } from 'hono' import

    { handle } from 'hono/vercel' const app = new Hono().basePath('/api') app.get('/hello', (c) => { return c.json({ message: 'Hello Next.js!' }) }) export const GET = handle(app) export const POST = handle(app) // https://hono.dev/docs/getting-started/nextjs より引用し一部改変 39
  15. 実装例 // app/api/(hono)/[[...slug]]/route.tsに以下のファイルを配置 import { Hono } from 'hono' import

    { handle } from 'hono/vercel' const app = new Hono().basePath('/api') app.get('/hello', (c) => { return c.json({ message: 'Hello Next.js!' }) }) export const GET = handle(app) export const POST = handle(app) // https://hono.dev/docs/getting-started/nextjs より引用し一部改変 40 アダプタとして hono/vercelをimport
  16. 実装例 // app/api/(hono)/[[...slug]]/route.tsに以下のファイルを配置 import { Hono } from 'hono' import

    { handle } from 'hono/vercel' const app = new Hono().basePath('/api') app.get('/hello', (c) => { return c.json({ message: 'Hello Next.js!' }) }) export const GET = handle(app) export const POST = handle(app) // https://hono.dev/docs/getting-started/nextjs より引用し一部改変 41 アダプタとして hono/vercelをimport Next.jsは特定名でexport された関数がリクエストを ハンドルする hono/vercelのhandleで 囲って関数を実装
  17. Optional Catch-all segments の処理順 . └── api ├── (hono) │

    └── [[...slugs]] │ └── route.ts (1) └── foo └── route.ts (2) 48 /api/fooへの処理 (2)のRoute Handlerが 処理する (1)のroute.tsに書いた /api/fooのハンドラは 実行されない
  18. Optional Catch-all segments の処理順 . └── api ├── (hono) │

    └── [[...slugs]] │ └── route.ts (1) └── foo └── route.ts (2) 49 左のような構造のコー ドを想定 (1)のroute.tsに書いた /api/fooのハンドラは 実行されない Optional Catch-all segmentsの 処理優先順位が低い
  19. Optional Catch-all segments - Optional Catch-all segmentsの処理優先順位 が低い - つまりRoute

    Handlerの実装をそのままに Honoの実装を増やせる - 段階的な移行が可能 50
  20. 64 まとめ - Next.jsで提供するHTTP APIをHonoによって 提供 - Hono OpenAPIでOpenAPIの力を手にいれる -

    Next.jsでもコードファーストでAPI仕様を生成 する - Honoを導入することで豊富なエコシステムを 獲得