私が歌川です

@utgwkk が書いている

utgw.netをNext.js App RouterからHonoに移行した

はじめに

utgw.netをNext.js App RouterからHonoに移行しました。Claude Codeが一晩でやってくれました。

utgw.net は id:utgwkk のホームページです。前回までのあらすじは以下の記事を読んでください。

blog.utgw.net

blog.utgw.net

なぜ移行したのか

個人サイトなので好きにしたらいい、というのは前提であるとして……。

Next.js App Router (以下、単にApp Routerと書く) のキャッシュ戦略と、自分のホームページでやりたいキャッシュ戦略が噛み合っていないのをいい加減解決しよう、というのが移行のモチベーションです。

utgw.net には、SpeakerDeckのRSSフィードから最新のスライド一覧を取得して表示する面があります。都度SpeakerDeckにHTTPリクエストを送信すると、レイテンシが増大したり、SpeakerDeck側に負荷がかかったりします。スライド一覧はある程度キャッシュしつつ、スライドを公開したら一覧にも反映されてほしくなります。

App Routerには時間ベースのキャッシュ破棄の仕組みがあるため、一見するとこれが使えそうに見えます*1。つまり、page.tsx ファイルに以下のように書いたら10分キャッシュしてくれそうです。

export const revalidate = 1200;

ところが、これだけだとビルド時にデータキャッシュが焼き込まれ、再度ビルド・デプロイしないとSpeakerDeckのスライド一覧が更新されなくなってしまいます。Pages Router時代は getServerSideProps 関数でデータフェッチしつつ Cache-Control レスポンスヘッダをつけたらよかったのですが、同じことをApp Routerで実現する方法が分かりませんでした。完全にキャッシュを無効化することでスライド一覧が更新されるようになりますが、これは都度SpeakerDeckにリクエストを投げていることになり、やりたいことに反します。Next.js middlewareで無理やり Cache-Control レスポンスヘッダをつけようとしたのですが、デプロイしてみるとNext.jsのどこかの層でヘッダごと叩き落とされていたように記憶しています。

長々と書いたけど、要するに「スライド一覧をキャッシュしつつ適度に更新されるようにしたい」というのが最大のモチベーションでした。ここまで書いて思ったけど、今ならAIに聞いたら解決できたのかも。

構成

移行前の構成は以下の通りです。

  • ペライチのWebページとリダイレクト機能がある
  • Next.js App Router
  • AWS Lambda上で動いている
  • 前段にCloudFrontがある

移行後に期待することは「壊れていない」ぐらいしかなくて気楽です。

移行の流れ

テストを書く

移行に先んじて、リダイレクト機能が動いていることや、画像がリンク切れになっていないことなどを確かめるE2Eテストを書きました。テストがあることで、どういう状態が期待されているのか明確になります。

github.com

Hono (hono/jsx) に移行する

期待する状態が明確になったので、あとは移行するだけです。

まずはおもむろに CLAUDE.md ファイルを用意します。AIコーディングエージェントに移行してもらおう、という算段です。

github.com

あとはClaude Codeを開くだけです。「Next.jsからHono (hono/jsx) に移行してください」というプロンプトでPlanしてもらったあと作業に取りかかってもらったらだいたい完了したと思います。

github.com

デプロイ時に必要なスクリプトのコピーを忘れていてLambda関数がコケるようになったのですが、そこを直したら無事に動くようになりました。

github.com

ちなみに、HonoはネイティブでLambda上で動作する*2のでLambda Web Adapterは外せます。

github.com

ESLint flat configに移行する

ESLintを更新しきれていなかったのですが、重い腰を上げて (プロンプトを投げて) flat configに移行しました。

github.com

oxlint, oxfmtに移行する

欲が出たので、そのままoxlint, oxfmtに移行してもらいました。lintは速ければ速いほどいいですからね。

github.com

github.com

おわりに

App RouterからHonoに移行することで、狙い通り Cache-Control レスポンスヘッダでCDNキャッシュの制御をしやすくなりました。よかったですね。

自分の代わりに動いてくれる頭と手が増えるだけで物事が一気に進みはじめる、という事例でした。今年度からClaudeのProプランに課金しました。AI時代になっても個人サイトを技術の砂場にする流れは変わらず、むしろ加速していくでしょう。

あわせてよみたい

HTTPレベルのキャッシュについてはMDNの記事がよくまとまっているので、まずはそちらを読むとよいでしょう。

キャッシュやCDNについては以下の本が詳しいです*3

時間のないサイト運営者リング