リンクとナビゲーション
Next.jsでルート間を移動する方法は4つあります:
<Link>
コンポーネントの使用useRouter
フックの使用(クライアントコンポーネント)redirect
関数の使用(サーバーコンポーネント)- ネイティブHistory APIの使用
このページでは、これらの各オプションの使用方法と、ナビゲーションの仕組みについて詳しく説明します。
<Link>
コンポーネント
<Link>
は、HTML <a>
タグを拡張し、ルート間のプリフェッチとクライアントサイドのナビゲーションを提供する組み込みコンポーネントです。Next.jsでルート間を移動する主要かつ推奨される方法です。
next/link
からインポートし、コンポーネントにhref
プロパティを渡すことで使用できます:
<Link>
に渡せる他のオプションのプロパティもあります。詳細はAPIリファレンスを参照してください。
useRouter()
フック
useRouter
フックにより、クライアントコンポーネントからプログラム的にルートを変更できます。
useRouter
メソッドの完全なリストについては、APIリファレンスを参照してください。
推奨: 特別な要件がない限り、ルート間の移動には
<Link>
コンポーネントを使用してください。
redirect
関数
サーバーコンポーネントでは、代わりにredirect
関数を使用します。
補足:
redirect
はデフォルトで307(一時的リダイレクト)ステータスコードを返します。サーバーアクション内で使用する場合、303(他を参照)を返します。これは通常、POSTリクエストの結果として成功ページにリダイレクトする際に使用されます。redirect
は内部的にエラーをスローするため、try/catch
ブロック外で呼び出す必要があります。redirect
はクライアントコンポーネントのレンダリングプロセス中に呼び出せますが、イベントハンドラー内では呼び出せません。代わりにuseRouter
フックを使用してください。redirect
は絶対URLも受け入れ、外部リンクにリダイレクトするために使用できます。- レンダリングプロセスの前にリダイレクトする場合は、
next.config.js
またはミドルウェアを使用してください。
詳細はredirect
APIリファレンスを参照してください。
ネイティブHistory APIの使用
Next.jsでは、ネイティブのwindow.history.pushState
とwindow.history.replaceState
メソッドを使用して、ページをリロードせずにブラウザの履歴スタックを更新できます。
pushState
とreplaceState
の呼び出しは、Next.jsルーターと統合されており、usePathname
とuseSearchParams
と同期できます。
window.history.pushState
ブラウザの履歴スタックに新しいエントリを追加するために使用します。ユーザーは前の状態に戻ることができます。例えば、製品のリストをソートする場合:
window.history.replaceState
ブラウザの履歴スタックの現在のエントリを置き換えるために使用します。ユーザーは前の状態に戻ることができません。例えば、アプリケーションのロケールを切り替える場合:
ルーティングとナビゲーションの仕組み
App Routerは、ルーティングとナビゲーションにハイブリッドアプローチを使用します。サーバー側では、アプリケーションコードがルートセグメントごとに自動的にコード分割されます。クライアント側では、Next.jsがルートセグメントをプリフェッチし、キャッシュします。つまり、ユーザーが新しいルートに移動しても、ブラウザはページをリロードせず、変更されたルートセグメントのみが再レンダリングされます - これにより、ナビゲーション体験とパフォーマンスが向上します。
1. コード分割
コード分割により、アプリケーションコードをブラウザでダウンロードおよび実行される小さなバンドルに分割できます。これにより、各リクエストで転送されるデータ量と実行時間が削減され、パフォーマンスが向上します。
サーバーコンポーネントにより、アプリケーションコードはルートセグメント別に自動的にコード分割されます。つまり、現在のルートに必要なコードのみがナビゲーション時にロードされます。
2. プリフェッチ
プリフェッチは、ユーザーが訪れる前にバックグラウンドでルートを事前に読み込む方法です。
Next.jsでは、ルートは2つの方法でプリフェッチされます:
<Link>
コンポーネント:ルートは、ユーザーのビューポート内に表示されると自動的にプリフェッチされます。プリフェッチは、ページが最初にロードされたとき、またはスクロールによって表示されたときに行われます。router.prefetch()
:useRouter
フックを使用して、プログラム的にルートをプリフェッチできます。
<Link>
のデフォルトのプリフェッチ動作(prefetch
プロパティが未指定またはnull
に設定されている場合)は、loading.js
の使用方法によって異なります。最初のloading.js
ファイルまでのコンポーネントの「ツリー」に沿って、共有レイアウトのみが30秒間プリフェッチおよびキャッシュされます。これにより、動的ルート全体をフェッチするコストが削減され、ユーザーにより良いビジュアルフィードバックを提供するためにインスタントローディング状態を表示できます。
prefetch
プロパティをfalse
に設定することで、プリフェッチを無効にできます。または、prefetch
プロパティをtrue
に設定することで、ロード境界を超えたページ全体のデータをプリフェッチできます。
詳細については、<Link>
APIリファレンスを参照してください。
補足:
- プリフェッチは開発モードでは無効で、本番モードでのみ有効です。
3. キャッシュ
Next.jsには、ルーターキャッシュと呼ばれるインメモリのクライアント側キャッシュがあります。ユーザーがアプリ内を移動する際、プリフェッチされたルートセグメントと訪問されたルートのReactサーバーコンポーネントペイロードがキャッシュに保存されます。
これは、ナビゲーション時にキャッシュが可能な限り再利用され、サーバーへの新しいリクエストが行われないことを意味し、リクエスト数と転送されるデータを削減することでパフォーマンスが向上します。
ルーターキャッシュの仕組みとその設定方法について詳しく学びましょう。
4. 部分的レンダリング
部分的レンダリングとは、ナビゲーション時に変更されるルートセグメントのみがクライアント上で再レンダリングされ、共有セグメントが保持されることを意味します。
例えば、/dashboard/settings
と/dashboard/analytics
のような2つの兄弟ルート間を移動する場合、settings
ページはアンマウントされ、analytics
ページは新しい状態でマウントされ、共有されるdashboard
レイアウトは保持されます。この動作は、/blog/[slug]/page
のような同じ動的セグメント上の2つのルート(/blog/first
から/blog/second
へ移動)の間にも存在します。
部分的レンダリングがない場合、各ナビゲーションでクライアント上でページ全体が再レンダリングされます。変更されるセグメントのみをレンダリングすることで、転送されるデータ量と実行時間が削減され、パフォーマンスが向上します。
5. ソフトナビゲーション
ブラウザはページ間を移動する際に「ハードナビゲーション」を実行します。Next.jsのAppルーターは、ページ間の「ソフトナビゲーション」を可能にし、変更されたルートセグメントのみが再レンダリングされます(部分的レンダリング)。これにより、ナビゲーション中にクライアントのReactステートが保持されます。
6. 戻る・進むナビゲーション
デフォルトで、Next.jsは戻る・進むナビゲーションのスクロール位置を維持し、ルーターキャッシュのルートセグメントを再利用します。
7. pages/
とapp/
間のルーティング
pages/
からapp/
に段階的に移行する場合、Next.jsルーターはpages/
とapp/
間のハードナビゲーションを自動的に処理します。pages/
からapp/
への遷移を検出するために、アプリルートの確率的チェックを活用するクライアントルーターフィルターがあり、これは時折偽陽性を生じる可能性があります。デフォルトでは、このような発生は非常にまれで、偽陽性の可能性を0.01%に設定しています。この可能性は、next.config.js
のexperimental.clientRouterFilterAllowedRate
オプションでカスタマイズできます。偽陽性率を下げると、クライアントバンドルに生成されるフィルターのサイズが増加することに注意してください。
代替として、このハンドリングを完全に無効にしてpages/
とapp/
間のルーティングを手動で管理する場合は、next.config.js
でexperimental.clientRouterFilter
をfalse
に設定できます。この機能が無効の場合、pages
内の動的ルートと重複するアプリルートには、デフォルトで適切にナビゲーションできません。