はじめに
Next.js 13以降で導入された App Router。
勉強も兼ねて、Page Router で作ったアプリを App Router に移行しようとしたところ、思いの外つまずくポイントがいくつかありました。
本記事は、備忘録として自分がハマったポイントをまとめたものです。
✅ App Routerの全体像や使い方を詳しく知りたい人は、まずは公式ドキュメントを見るのがおすすめです:
Next.js App Router移行ガイド(公式)
つまずきポイント①:移行したはずのページが 404 になる
状況
まず Page Router で作ったトップページを移行しようと思い、 app/
フォルダ配下に layout.tsx
と page.tsx
を作成し、元の Page Router のトップページは名前を変えました。
※競合するページがあると、エラーになります
しかし、画面にアクセスすると 404 (存在しないページ)と表示されてしまう...。アクセスするパスはあっているはずなのに何故?
そんな現象が発生しました。
原因と対応
next.config.mjs
に次のような設定が入っていたことが原因でした。
pageExtensions: ['page.tsx', 'ts'],
この設定だと、.page.tsx
と .ts
の拡張子ファイルは画面として認識されますが、page.tsx
というファイル名は拡張子が違うので、画面として認識されません。
以下のように設定を変更し、解決しました。
pageExtensions: ['tsx', 'ts']
後から調べたところ pageExtensions
の設定を削除しても、解決していました。
つまずきポイント②:layout.tsx
に _app.tsx
の中身をそのまま移すとエラーになる
状況
画面にアクセスできるようになったものの、移行した layout.tsx
にて次のようなエラーが出ていました。
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `App`.
なんだか型が不正と言われています。
この後 chatGPT にもエラー内容を投げてみたのですが、返ってきたのは概ね「export が間違っているのでは」との回答。
しかし実際直すべき export は見つからず、中々解決につながりませんでした。。
原因と対応
_app.tsx
からコピーしてきた以下のコードに原因がありました。
type AppPropsWithLayout = AppProps & {
Component: NextPage;
};
export default function App({ Component, pageProps }: AppPropsWithLayout) {
App の引数として { Component, pageProps }
を受け取る形で書いていたのですが、layout では { children }
を受け取るため、内容が一致せずエラーになります。
※ちゃんと公式の移行ガイドにもそのようなコメントが書いてありました。。
以下のようにコードを修正し、解決しました。
type AppPropsWithLayout = AppProps & {
children: React.ReactNode;
};
export default function App({ children }: AppPropsWithLayout) {
おわりに
実際は更に色々なエラーが出て、修正して...を繰り返していたのですが、個人的に時間をかけてしまった内容をピックアップしてみました。
同じようなところで苦しんでしまった人の参考になれば、幸いです!