コンテンツにスキップ

リンクとナビゲーション

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

このページでは、これらの各オプションの使用方法を説明し、ナビゲーションの仕組みについて詳しく解説します。

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

next/linkからインポートし、コンポーネントにhrefプロップを渡すことで使用できます。

app/page.tsx
import Link from 'next/link'
 
export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}

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

useRouter()フック

useRouterフックを使用すると、クライアントコンポーネントからプログラムでルートを変更できます。

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関数

サーバーコンポーネントの場合は、代わりに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')
  }
 
  // ...
}

知っておくと良いこと:

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

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

ネイティブHistory APIの使用

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

pushStatereplaceStateの呼び出しは、Next.jsルーターに統合されており、usePathnameおよびuseSearchParamsと同期できます。

window.history.pushState

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

'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

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

'use client'
 
import { usePathname } from 'next/navigation'
 
export function LocaleSwitcher() {
  const pathname = usePathname()
 
  function switchLocale(locale: string) {
    // e.g. '/en/about' or '/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. コード分割

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

サーバーコンポーネントを使用すると、アプリケーションコードをルートセグメントごとに自動的にコード分割できます。つまり、現在のルートに必要なコードのみがナビゲーション時にロードされます。

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. 部分レンダリング

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

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

How partial rendering works

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

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

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

6. 戻るおよび進むナビゲーション

デフォルトでは、Next.jsは、戻るおよび進むナビゲーションのスクロール位置を維持し、ルーターキャッシュのルートセグメントを再利用します。

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

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

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