メインコンテンツまでスキップ

リンクとナビゲーション

Next.jsでルート間をナビゲートする方法は4つあります:

このページでは、これらの各オプションの使用方法を説明し、ナビゲーションがどのように機能するかを詳しく見ていきます。

<Link>はHTMLの<a>タグを拡張した組み込みコンポーネントであり、プリフェッチとルート間のクライアントサイドナビゲーションを提供します。それは、Next.jsでルート間をナビゲートする際の主要かつ推奨される方法です。

next/linkからインポートし、このコンポーネントにhref prop を渡して使用できます:

app/page.tsx
import Link from 'next/link'

export default function Page() {
return <Link href="/dashboard">Dashboard</Link>
}

<Link>に渡すことができるその他のオプションの props もあります。詳細はAPIリファレンスを参照してください。

useRouter()フック

useRouterフックを利用すると、Client Componentsからプログラム的にルートを変更できます。

app/page.js
'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
const router = useRouter()

return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}

useRouterメソッドの完全なリストについては、APIリファレンスを参照してください。

おすすめ: useRouterを使用する特定の要件がない限り、ルート間をナビゲートするには<Link>コンポーネントを使用してください。

redirect関数

Server Componentsの場合、redirect関数を使用してください。

app/team/[id]/page.tsx
import { redirect } from 'next/navigation'

async function fetchTeam(id: string) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}

export default async function Profile({ params }: { params: { id: string } }) {
const team = await fetchTeam(params.id)
if (!team) {
redirect('/login')
}

// ...
}

Good to know:

  • redirectはデフォルトで307(Temporary Redirect)ステータスコードを返します。Server Actionで使用すると、303(See Other)を返します。これはPOSTリクエストの結果として成功ページにリダイレクトする際によく使用されます。
  • redirectは内部でエラーをスローしますので、try/catchブロックの外部で呼び出す必要があります。
  • redirectはClient Componentsのレンダリングプロセス中には呼び出せますが、イベントハンドラー内では呼び出せません。その場合はuseRouterフックを使用できます。
  • redirectは絶対URLも受け付け、外部リンクへのリダイレクトにも使用できます。
  • レンダリングプロセスの前にリダイレクトしたい場合、next.config.jsまたはMiddlewareを使用してください。

詳細については、redirect APIリファレンスを参照してください。

ネイティブのHistory APIを使用する

Next.jsでは、ネイティブのwindow.history.pushStatewindow.history.replaceStateメソッドを使用して、ページをリロードすることなくブラウザの履歴スタックを更新できます。

pushStatereplaceStateの呼び出しはNext.js Routerに統合されており、usePathnameuseSearchParamsと同期できます。

window.history.pushState

これを使用して、ブラウザの履歴スタックに新しいエントリを追加します。ユーザーは前の状態に戻ることができます。たとえば、製品のリストをソートするには次のようにします:

app/ui/sort-products.tsx
'use client'

import { useSearchParams } from 'next/navigation'

export default function SortProducts() {
const searchParams = useSearchParams()

function updateSorting(sortOrder: string) {
const params = new URLSearchParams(searchParams.toString())
params.set('sort', sortOrder)
window.history.pushState(null, '', `?${params.toString()}`)
}

return (
<>
<button onClick={() => updateSorting('asc')}>Sort Ascending</button>
<button onClick={() => updateSorting('desc')}>Sort Descending</button>
</>
)
}

window.history.replaceState

これを使用して、ブラウザの履歴スタック上の現在のエントリを置き換えます。ユーザーは前の状態に戻ることはできません。たとえば、アプリケーションのロケールを切り替えるには次のようにします:

app/ui/locale-switcher.tsx
'use client'

import { usePathname } from 'next/navigation'

export function LocaleSwitcher() {
const pathname = usePathname()

function switchLocale(locale: string) {
// 例: '/en/about' または '/fr/contact'
const newPath = `/${locale}${pathname}`
window.history.replaceState(null, '', newPath)
}

return (
<>
<button onClick={() => switchLocale('en')}>English</button>
<button onClick={() => switchLocale('fr')}>French</button>
</>
)
}

ルーティングとナビゲーションの動作

App Routerは、ルーティングとナビゲーションにハイブリッドアプローチを採用しています。サーバーでは、アプリケーションコードがルートセグメントによって自動的にコード分割されます。そしてクライアントでは、Next.jsはルートセグメントをプリフェッチし、キャッシュします。これにより、ユーザーが新しいルートにナビゲートするとき、ブラウザはページをリロードせず、変化するルートセグメントのみが再レンダリングされるため、ナビゲーション体験とパフォーマンスが向上します。

1. コードスプリッティング

コードスプリッティングは、アプリケーションコードを小さなバンドルに分割してブラウザにダウンロードおよび実行することができます。これにより、データ転送量と各リクエストの実行時間が削減され、パフォーマンスが向上します。

Server Componentsは、アプリケーションコードをルートセグメントによって自動的にコード分割することを可能にします。これにより、ナビゲーション時には現在のルートに必要なコードのみがロードされます。

2. プリフェッチ

プリフェッチとは、ユーザーが訪れる前にバックグラウンドでルートを事前にロードする方法です。

Next.jsではルートは次の2つの方法でプリフェッチされます:

  • <Link>コンポーネント:ルートはユーザーのビューポートに表示されると自動的にプリフェッチされます。プリフェッチは、ページが最初に読み込まれたときやスクロールを通じてビューポートに表示されるときに行われます。
  • router.prefetch()useRouterフックを使用してルートをプログラム的にプリフェッチできます。

<Link>のデフォルトのプリフェッチ動作(つまり、prefetchプロップが未指定またはnullに設定されている場合)は、loading.jsの使用状況によって異なります。共有レイアウトのみが、最初のloading.jsファイルまでのレンダリング「tree」の下にプリフェッチされ、30s間キャッシュされます。これにより、動的ルート全体をフェッチするコストが削減され、ユーザーにより良いビジュアルフィードバックを提供するための即時読み込み状態を表示することができます。

プリフェッチを無効にするには、prefetchプロップをfalseに設定します。代わりに、プリフェッチをtrueに設定することにより、ロード境界を超えた完全なページデータをプリフェッチすることができます。

詳細については、<Link>APIリファレンスを参照してください。

Good to know:

  • プリフェッチは、開発時には無効で、プロダクションのみで有効です。

3. キャッシング

Next.jsには、Router Cacheと呼ばれるメモリ内クライアントサイドキャッシュがあります。ユーザーがアプリをナビゲートすると、プリフェッチされたルートセグメントと訪問したルートのReact Server Component Payloadがキャッシュに保存されます。

これは、ナビゲーション時に新たにサーバーにリクエストを送るのではなく、キャッシュができるだけ再利用されることを意味し、リクエスト数やデータ転送量を削減することでパフォーマンスを向上させます。

Router Cache の動作と構成方法について詳しく学んでください。

4. 部分レンダリング

部分レンダリングとは、ナビゲーション時に変更されるルートセグメントのみがクライアント側で再レンダリングされ、共有セグメントは保持されることを意味します。

たとえば、2つの兄弟ルート/dashboard/settings/dashboard/analyticsの間でナビゲートする場合、settingsページはアンマウントされ、analyticsページは新しい状態でマウントされ、共有のdashboardレイアウトは保持されます。この動作は、同じ動的セグメント上の2つのルート間でも見られます。たとえば、/blog/[slug]/pageで、/blog/firstから/blog/secondへのナビゲーション。

部分レンダリングの仕組み部分レンダリングの仕組み

部分レンダリングがなければ、それぞれのナビゲーションでページ全体がクライアント側で再レンダリングされます。変更されるセグメントのみをレンダリングすることで、データ転送量と実行時間が削減され、パフォーマンスが向上します。

5. ソフトナビゲーション

ブラウザはページ間のナビゲーション時に「ハードナビゲーション」を行います。Next.jsのApp Routerはページ間の「ソフトナビゲーション」を有効にし、変更されたルートセグメントだけが再レンダリングされるようにします(部分レンダリング)。これにより、ナビゲーション中のクライアント側React状態が保持されます。

6. 戻ると進むのナビゲーション

デフォルトでは、Next.jsはバックワードおよびフォワードナビゲーションの際にスクロール位置を維持し、Router Cache内のルートセグメントを再利用します。

7. pages/app/間のルーティング

pages/からapp/への段階的な移行時に、Next.jsのルーターは2つの間でのハードナビゲーションを自動的に処理します。pages/からapp/への移行を検出するために、appルートの確率的なチェックを活用するクライアントルーターフィルターがありますが、これにより間違ったポジティブが発生する可能性があります。デフォルトでは、そのような発生は非常にまれであるべきであり、我々は誤ったポジティブの発生率を0.01%に設定しています。この発生率は、next.config.jsexperimental.clientRouterFilterAllowedRateオプションを使用してカスタマイズできます。誤ったポジティブ率を下げると、クライアントバンドルで生成されるフィルタのサイズが増加することに注意してください。

また、experimental.clientRouterFilterfalseに設定して、この処理を完全に無効化し、pages/app/間のルーティングを手動で管理することを好む場合もあります。この機能が無効になっている場合、appルートと重なるpages内の動的ルートはデフォルトで適切にナビゲートされません。