👋

Next.js App RouterのParallel Routesとは?仕組みと使い方まとめ

に公開

はじめに

Next.jsのApp Routerを学んでいたときに、「Parallel Routes」という見慣れない機能を見つけました。
同じレイアウト内で1つまたは複数のページを同時にレンダリングできる仕組みで、ダッシュボードやスプリットレイアウトのような構成と相性が良く、実際に現場でも同様のレイアウトが使われていたため、興味を持って調べてみました。
備忘も兼ねて、要点をまとめておきます。

Parallel Routesとは?

Parallel Routes は、Next.jsのApp Routerで導入された機能で、1つのURLに対して複数のルートを並列に扱える仕組みです。
通常のルーティングでは、特定のURLに対して1つのページコンポーネントが表示されますが、Parallel Routesを使うと、複数の「スロット(slot)」に対応するUIを同時に表示できます。

例えば「左側に一覧、右側に詳細」といったスプリットビューの構成といったUIが実現しやすくなります。

この機能は @slotName というディレクトリ構成によって実現されており、それぞれのスロットに別々のページやローディング、エラーハンドリングを定義できます。これにより、UIの部分的な再描画や状態の分離が簡単に行えるようになります。

ディレクトリ構成と基本のルール

Parallel Routesを使うには、@スロット名 という特別な名前のディレクトリを使って構成します。
この @ で始まる名前空間が、それぞれの スロット(UIの描画枠) として機能します。

以下は、@right@left という2つのスロットを持つ構成例です:

app/
  layout.tsx
  page.tsx
  @right/
    page.tsx
  @left/
    page.tsx

このとき、layout.tsx では @right@left に対応する rightleft が引数として自動で渡されます:

export default function Layout({
  children,
  right,
  left,
}: {
  children: React.ReactNode
  right: React.ReactNode
  left: React.ReactNode
}) {
  return (
    <>
      {children}
      {right}
      {left}
    </>
  )
}

スロット名と関数の引数名を一致させることで、Next.jsがそれぞれのスロットの中身を自動的に割り当ててくれます。

それぞれのスロットは 独立したルートとして動作し、個別に page.tsx や loading.tsx、error.tsx を持つことができます。
1つのルートパスに対して複数のUIを同時に表示・制御できる柔軟な構造が、ディレクトリ名と引数名のルールだけで実現されているのがParallel Routesの特徴です。

コードで理解するParallel Routesの基本

ここでは、実際のコードを通してParallel Routesの挙動を見ていきます。
以下の構成を例に、「右側に詳細」「左側に一覧」を並列で表示するシンプルなスプリットレイアウトを想定します。

ディレクトリ構成

app/
  layout.tsx
  @left/
    page.tsx
  @right/
    page.tsx

layout.tsx

export default function Layout({
  left,
  right,
}: {
  left: React.ReactNode
  right: React.ReactNode
}) {
  return (
    <div style={{ display: 'flex' }}>
      <aside style={{ flex: 1, borderRight: '1px solid #ccc' }}>{left}</aside>
      <main style={{ flex: 2 }}>{right}</main>
    </div>
  )
}

ここでは leftright というスロットを2カラムで表示しています。
各スロットに対応する @left/page.tsx@right/page.tsx の中身は、それぞれ以下のように記述できます。

@left/page.tsx

export default function LeftPage() {
  return <ul>一覧(左カラム)</ul>
}

@right/page.tsx

export default function RightPage() {
  return <div>詳細(右カラム)</div>
}

表示結果

1つのURL(例:/dashboard)にアクセスすると、leftright の2つのスロットが同時に表示されます。
それぞれの内容は完全に独立しており、ページ遷移時にも状態を保ったまま更新できます。

よくあるユースケース

Parallel Routesは、複数のUIを同時に表示・制御できる仕組みなので、ページ全体の構成が分かれているようなレイアウトに特に向いています。
以下に、実際の開発現場でもよく見かける活用例を紹介します。

スプリットビュー(一覧+詳細)

2カラム構成

  • 左側:@left に一覧のリスト
  • 右側:@right に選択された項目の詳細

ダッシュボード+サブ機能

管理画面などで、メインのダッシュボードと右側に「通知」や「設定」といったサブビューを表示する場合にも有効です。

チャットアプリ構成

  • 左側:チャットルーム一覧(@sidebar)
  • 右側:選択中のルームのメッセージ一覧(@main)

Parallel Routesは、UIを分割した構成を持つWebアプリケーション全般に活用できます。

まとめ

Parallel Routesで特に良いと感じたのは、ローディング・エラー・NotFoundといったUIをスロットごとに個別に分けられる点です。
アプリ全体のUXを壊さずに、一部分だけ状態を切り替えられるのは非常に便利でした。
また、各スロットがそれぞれ独立したページとして完結する構造になっているため、ページごとの責務や役割を明確に分離できる点も魅力です。
複数の画面要素が共存するようなレイアウトでも、実装が複雑になりすぎず、整理された構成を保てると感じました。

Discussion