MemoDripのNext.jsをPages RouterからApp Router移行した

MemoDripというコーヒーを淹れた際に感想をメモできるWebサービスを運営しています。

このサービスではフロントエンドにNext.jsを利用しています。先日満を持してこのNext.jsをApp Routerに移行したため、移行時にやったこととやった結果感じたことを書いておきます。

やったこと

基本的にはドキュメントにあったマイグレーションガイドをなぞっていった。
手順としてはそうなんだけど、一部ピックアップして書いておく

  1. _app, _layoutを置き換える
  2. ページコンポーネント回りを移動する
  3. 必要に応じてクライアントコンポーネントとサーバーコンポーネントに分ける
  4. API Routeも移動する

_app, _layoutを置き換える

app/layout.tsxに置き換えた
ベースになるmetaタグ回りと、RootLayoutにlangと共通処理の差し込みを行った。

割とあっさり移行したのでほんとにこれでいいのか?という気がしている。

ページコンポーネント回りを移動する

src/page に置いていたコンポーネントを src/app に移動した。

そのうえで、 getServerSideProps などのサーバー側で動く処理を置き換えた。
だいたいデータの取得を行ってコンポーネントに渡しているので引き続きその様に。

以前まではここを見ればどういったレンダリング方式かが分かったが、今後はどこからがクライアントコンポーネントなんだ?となりそう。

必要に応じてクライアントコンポーネントとサーバーコンポーネントに分ける

App Routerではサーバーコンポーネントが推されているようで、なるべくサーバーコンポーネントにするように対応を行った。
これまでは、SSRかCSRかみたいな判断があったが、またちょっと違った感覚だなと感じる。

基本的にはサーバーコンポーネントにできるようにし、特に認証が絡むコンポーネントのみコンポーネントを切り出し、クライアントコンポーネントにした。この兼ね合いでPages Rouerの時に行っていた構造からは変更が伴う部分も多く出てきた。

Pages Routerの頃は、なるべくpageコンポーネントでfetchを行い下層コンポーネントにバケツリレーをとる方式をよく行っていたが、CSRが必要な場合は子や孫などツリーの先のコンポーネントに寄せるようにした。

page/
└── parent/
    └── child/
        └── grandchild/ // なるべくここだけクライアントコンポーネントにする

API Routeも1と同じような対応をとる

ちょっとした処理の兼ね合いでAPI Routeも置いていて、そちらも移行が必要になった。

こちらは、以下の対応になる

  1. app/api/ への移行
  2. api/hoge.ts から app/api/hoge/route.ts に移動&リネーム

Next.js v15からヘッダー回りに変更が入っているが、そこは割愛。

対象の位置に移動してリネームするだけで動いた。

感じたこと

計測していないのが勿体ないのですが、サーバーコンポーネントへの移行のおかげかページが表示されるまでが体感でも分かるほど早くなった。App Routerサマサマ。

やるまではAppRouterへの移行でどこかしら壊れるのかなとか、サーバーコンポーネント化によってSSRみたいな速度になるんでは?と思っていたけど特にそんなことはなかったし何より早くなった。Lighthouseのスコアなんかもいい影響が出るのではと思うが、いいことだけじゃないだろうという気がしており引き続き要確認というステータス。

そこまで大きなアプリケーションでは無いものの地味に時間がかかったので、切り替えるなら早い方がいいかもしれない。