ウェブエンジニア問題集

ルーティングとページ — App Routerのファイルベースルーティング入門

Webアプリには必ず「URLと画面の対応づけ」=ルーティングが必要です。Next.js(App Router)の最大の特徴は、この対応づけを設定ファイルではなくフォルダとファイルの配置だけで表現できることです。

この章では、app/ 配下のディレクトリ構成がそのままURLになる仕組みと、<Link> による画面遷移までを押さえます。

学習者学習者

ルーティングって、ライブラリを入れて設定ファイルに書くものだと思ってた。フォルダを作るだけでURLになるの…?

ファイルベースルーティングの仕組み

App Routerでは、app/ ディレクトリの中の**フォルダがURLの区切り(セグメント)**になり、そのフォルダに置いた page.tsx がそのURLで表示される画面になります。

src/app/
├── page.tsx          → /         (トップページ)
├── about/
│   └── page.tsx      → /about
└── blog/
    └── page.tsx      → /blog

つまり「/about というページを作りたい」なら、app/about/page.tsx を作るだけです。

// src/app/about/page.tsx
export default function AboutPage() {
  return <h1>このサイトについて</h1>;
}
先生先生

フォルダ名=URL、page.tsx=そのURLの中身。この2つの対応さえ掴めば、ルーティングの8割は理解したも同然だよ。

フォルダ構成がそのままURLになるイメージ

階層(ネスト)もフォルダで表現

フォルダを入れ子にすれば、URLも階層になります。

app/
└── blog/
    ├── page.tsx          → /blog
    └── settings/
        └── page.tsx      → /blog/settings

URLにならないフォルダ — page.tsx の有無がカギ

重要なルールがあります。page.tsx を置いたフォルダだけが、アクセス可能なURLになりますpage.tsx のないフォルダは、URLの一部にはなっても単体ではアクセスできません(コンポーネントやユーティリティを置く置き場として使えます)。

app/
└── dashboard/
    ├── page.tsx          → /dashboard(アクセス可能)
    ├── DashboardChart.tsx ← page.tsxではないのでURLにならない(部品置き場)
    └── settings/
        └── page.tsx      → /dashboard/settings(アクセス可能)

特別な意味を持つファイル名

App Routerでは、いくつかのファイル名が予約されており、それぞれ決まった役割を持ちます。本書で扱う主要なものをまとめます。

ファイル役割解説する章
page.tsxそのURLで表示される画面本章
layout.tsx配下のページで共有される枠第5章
loading.tsx読み込み中に表示するUI第8章
error.tsxエラー発生時に表示するUI第8章
not-found.tsx404のときに表示するUI第8章
route.tsAPIエンドポイント(画面ではなくデータ)

ページ間の遷移には、next/link<Link> を使います。HTMLの <a> タグの代わりに使うことで、ページ全体を再読み込みせずに高速に画面を切り替えられます(クライアントサイドナビゲーション)。

import Link from "next/link";
 
export default function Nav() {
  return (
    <nav>
      <Link href="/">ホーム</Link>
      <Link href="/about">このサイトについて</Link>
      <Link href="/blog">ブログ</Link>
    </nav>
  );
}

主な props:

prop説明
hrefstring(必須)遷移先のパス(/about など)
prefetchbooleanリンクを画面内に表示した時点で遷移先を先読みするか(既定で有効)
replaceboolean履歴を「追加」せず「置き換え」る(戻るボタンの挙動が変わる)
scrollboolean遷移後にページ先頭へスクロールするか(既定 true

現在のページを判定する — usePathname

ナビゲーションで「今いるページ」を強調表示したいときは、usePathname で現在のパスを取得します。フックなのでClient Component"use client")で使います。

"use client";
 
import Link from "next/link";
import { usePathname } from "next/navigation";
 
export default function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
  const pathname = usePathname();
  const isActive = pathname === href;
 
  return (
    <Link href={href} className={isActive ? "font-bold text-blue-600" : "text-gray-600"}>
      {children}
    </Link>
  );
}
学習者学習者

usePathname はなんで "use client" が要るの?

usePathname は「今ブラウザがどのURLにいるか」を読むフックで、ブラウザ側でしか動きません。フック全般がそうであるように、Client Componentでのみ使えます。この区別は第3章で扱った Server/Client の考え方そのものです。

コードから遷移する — useRouter

ボタンのクリックや処理完了後にプログラムから遷移したいときは、useRouter を使います(こちらもClient Component専用)。

"use client";
 
import { useRouter } from "next/navigation";
 
export default function LoginButton() {
  const router = useRouter();
 
  async function handleLogin() {
    await login();
    router.push("/dashboard"); // ログイン後にダッシュボードへ
  }
 
  return <button onClick={handleLogin}>ログイン</button>;
}

router.push(path) で遷移、router.replace(path) で履歴を置き換えて遷移、router.back() で戻る、といった操作ができます。

まとめ

  • App Routerはフォルダ=URL、page.tsx=その画面というファイルベースルーティング
  • page.tsx を置いたフォルダだけがアクセス可能なURLになる
  • layout.tsx / loading.tsx / error.tsx などのファイル名は予約されており、決まった役割を持つ
  • 内部リンクは <Link>(高速遷移+先読み)。<a> は外部リンク用
  • 現在地の判定は usePathname、コードからの遷移は useRouter(どちらもClient Component)

次の章では、複数のページで共通のヘッダーやサイドバーを表示する レイアウトと共通UI を扱います。layout.tsx の役割を理解すると、サイト全体の骨組みが作れるようになります。