App Router の基本

App Router とは

App Router は、「フォルダ/ファイル = URL」をルールとしたダイナミックルーティングです。Next.js 13 から プロジェクト直下の app/ を基準に page.tsx ファイルを配置します。

ルーティングの大原則

よくある構成例

app/
├── api/
│   └── route.tsx
├── layout.tsx
├── page.tsx
├── chat/
│   └── page.tsx
└── chat/
    ├── page.tsx
    └── [slug]/
        ├── page.tsx 
        ├── loading.tsx
        └── error.tsx

基本ルーティング

項目 説明
フォルダ app/chat/ /chat でアクセス
ページ page.tsx フォルダ内のページファイル
共通レイアウト1 layout.tsx HTMLの共通枠を利用
共通レイアウト2 template.tsx ページ遷移ごとに状態リセットされるレイアウト
ネスト(階層 URL) app/blog/[slug]/page.tsx /blog/abc でアクセス
動的パラメータ [param]、可変長は [...param] パラメーター取得

動的 & ネストルーティング

形式 フォルダ名 例 URL searchParams / params
単一 [id] /post/123 { id: '123' }
可変長 [...slug] /docs/a/b/c { slug: ['a','b','c'] }
オプション [[lang]] /en/blog or /blog { lang?: string }

ルートグループ & URL クリーン化

フォルダ名 (group) を使うと「URLに影響しない」グルーピングが可能です。

ファイル URL
app/(marketing)/landing/page.tsx /
app/(app)/landing/page.tsx /dashboard

ページ固有の補助ファイル

ファイル タイミング / 目的
loading.tsx データ取得待ち中に表示
error.tsx 例外捕捉してユーザフレンドリ表示
not-found.tsx notFound() 呼び出し時に表示

レイアウト

レイアウトとは

最新のNext.js では App Router (app/ ディレクトリ) を使ったレイアウト機能が導入されています。このレイアウトは React Server Components (RSC) をベースにしており、以前の pages/ ベースのルーティングとは異なる構造になっています。

レイアウトの特徴

  1. ルートごとのレイアウトが可能 layout.tsx
  2. レイアウトはデフォルトでサーバーコンポーネント
  3. レイアウトは children を使ってネスト可能
  4. 共有コンポーネント(ナビゲーションやフッター)を保持しつつ、ページだけ再レンダリング

レイアウトの配置

Next.jsのレイアウトファイルはデフォルトで app/layout.tsx が用意されています。

  • Next.js 12のレイアウトは「components/layout.js」

レイアウトの構造

Next.js 13の共通レイアウトは、Root Layoutchildrenで構成し、各コンテンツページはpage.tsxを配置して表示します。

RootLayout

RootLayoutアプリ共通のレイアウトで、「app/layout.tsx」に配置します。

app/
├── layout.tsx

metadata

metadata は、HTMLのタイトルや説明などを設定する機能です。

app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Next Chat',
  description: 'This is chat app sample.',
}

CSS

「global.css」をimportし、サイト全体のスタイルが反映されています。

import './globals.css'

レイアウトコンポーネント

レイアウト名は「RootLayout」で、ファンクションコンポーネントになっています。引数childrenは、React.ReactNode型を指定しています。

app/layout.tsx
export default function RootLayout({ children, }: { children: React.ReactNode}) {

}

children

レイアウト内で各ページコンポーネントを表示するには、childrenを利用します。ReactベースのためJSXでコーディングします。

app/layout.tsx
export default function RootLayout({ children, }: { children: React.ReactNode}) {
  return (
     <html lang="en">
       <body>{children}</body>
     </html>
  )
}

レイアウト修正

共通レイアウトファイル「app/layout.tsx」を修正します。

metadata

不要な部分を削除し、metadataのタイトルと説明文を修正します。

app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";

// metaデータ変更
export const metadata: Metadata = {
  title: "Next Chat",
  description: "Generated by create next app",
};

JSX

レイアウトのHTML(JSX)を修正します。

app/layout.tsx
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ja">
      <body>
        {children}
      </body>
    </html>
  );
}

確認

ウィンドウタイトルが変更されたか確認してみましょう。

トップページ

ルートページ

サイトのルートページ app/page.tsx を修正します。

app/page.tsx
export default function HomePage() {
    return (
        <main className="min-h-screen flex items-center justify-center bg-gradient-to-br from-sky-100 to-sky-400 p-6">
            <div className="text-center space-y-6">
                <h1 className="text-4xl md:text-6xl font-extrabold text-gray-800">
                    ようこそ、Next Chatへ!
                </h1>
                <p className="text-lg md:text-xl text-gray-600">
                    友達・チーム・AIとチャットしよう
                </p>
                <div className="space-x-4">
                    <a href="/login"
                        className="px-6 py-3 bg-sky-600 text-white rounded-xl shadow hover:bg-sky-700 transition">
                        ログイン
                    </a>
                    <a href="/register"
                        className="px-6 py-3 bg-white border border-sky-600 text-sky-600 rounded-xl hover:bg-sky-50 transition">
                        新規登録
                    </a>
                </div>
            </div>
        </main>
    );
}

Next.jsで作るチャットアプリ