コンテンツにスキップ

Chapter 4: レイアウトとページ

ホームページだけだったアプリケーションに,いよいよダッシュボードを追加します。Next.js のファイルシステムルーティングはフォルダ構造そのものが URL になるため,構成を理解するとページ追加が一気にスムーズになります。


この章で身につくこと

  • フォルダと page.tsx の組み合わせでルートを増やす
  • 複数ページで共通化できるレイアウトを layout.tsx で構築する
  • 部分的レンダリングやコロケーションの考え方を押さえる

基本のフォルダ構造とコロケーション

Next.js では フォルダ = URL セグメント です。

alt text

/app/dashboard/page.tsx を作れば /dashboard が開けるようになります。

alt text

/app/dashboard/page.tsx
export default function Page() {
  return <p>Dashboard Page</p>;
}

ブラウザで http://localhost:3000/dashboard を開き,「Dashboard Page」と表示されれば成功です。ルート配下で page.tsx と同じ階層に UI やテストを置けるのが コロケーション のメリットです。実際に /app/ui/app/lib もルート配下へ隣接しており,ファイルを探しやすく保っています。


サブページを増やす

ダッシュボード配下に以下 2 つのページを用意しましょう。

  1. /dashboard/customers<p>Customers Page</p> を返すページ
  2. /dashboard/invoices<p>Invoices Page</p> を返すページ

alt text

完成後のファイルは次のとおりです。

/app/dashboard/customers/page.tsx
export default function Page() {
  return <p>Customers Page</p>;
}
/app/dashboard/invoices/page.tsx
export default function Page() {
  return <p>Invoices Page</p>;
}

これで /dashboard/customers/dashboard/invoices がそれぞれ閲覧できるようになりました。


ネストされたレイアウトを作る

ダッシュボードでは複数ページでサイドバーなどを共有したいので,layout.tsx を追加します。/app/dashboard/layout.tsx を作り,次のコードを記述してください。

/app/dashboard/layout.tsx
import SideNav from '@/app/ui/dashboard/sidenav';

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
      <div className="w-full flex-none md:w-64">
        <SideNav />
      </div>
      <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
    </div>
  );
}

children には /dashboard 配下のページ(page.tsx)が自動的に入るため,サイドバーは固定したままコンテンツのみが切り替わります。これが 部分的レンダリング で,リンク移動時にもレイアウトが再描画されず,クライアント側で保持した状態が失われません。

alt text


Root Layout との違い

第 3 章で更新した /app/layout.tsx がアプリ全体を包む ルートレイアウト でした。

/app/layout.tsx
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

ルートレイアウトは <html><body> を編集でき,全ページ共通のスタイルやメタデータを定義します。一方 /app/dashboard/layout.tsx はダッシュボード専用で,サイドバーなど限られた範囲だけに作用します。複数のレイアウトを段階的に重ねられる点が App Router の大きな強みです。


部分的レンダリングのメリット

  • ページ間遷移でもレイアウトが保持されるため,アニメーションや入力途中のフォームなどがリセットされない
  • サーバー側で必要箇所のみをレンダリングし,無駄な再描写を避けられる
  • フォルダ構成と UI をコロケーションできるので,規模が大きくなっても構造が把握しやすい

ここまでできれば,ダッシュボードの骨組みが完成です。次章ではページ間の移動やナビゲーションを実装していきます。