1. ホーム
  2. Next.js

【Next.js】App Router でページを作る方法|page.tsx とフォルダ構成のルーティングを解説

Share

Next.js の App Router では、フォルダとファイルを置くだけでページ(URL)が作られます。ルーティングの設定を別に書く必要はありません。この記事では、App Router を使ったページの作り方を基礎から解説します。page.tsx の役割、フォルダ構成と URL の対応、共通レイアウト、<Link> によるページ遷移、そして [id] のような動的なページの作り方まで、手を動かしながら理解できるように順番に説明します。なお、ここでは Next.js 13 以降で標準になった app ディレクトリ(App Router)を前提にしています。

page.tsx がページになる

App Router では、app ディレクトリの中に置いた page.tsx(または page.js)というファイルが、そのフォルダに対応する URL のページになります。まずはトップページを作ってみましょう。app/page.tsx がサイトのルート(/)に対応します。

app/page.tsx
export default function Home() {
  return (
    <main>
      <h1>トップページ</h1>
      <p>ようこそ!</p>
    </main>
  );
}

ポイントは、ページになるコンポーネントを export default で書き出すことです。この page.tsx を置くだけで、開発サーバー(npm run dev)を起動すると http://localhost:3000/ にこのページが表示されます。特別なルーティング設定は不要です。

フォルダ名がそのまま URL になる

新しいページを追加したいときは、app の中にフォルダを作り、その中に page.tsx を置きます。フォルダ名がそのまま URL のパスになります。たとえば「会社概要」ページを /about に作るなら、次のようにします。

app/about/page.tsx
export default function About() {
  return (
    <main>
      <h1>会社概要</h1>
    </main>
  );
}

フォルダの階層をそのまま URL に対応させられるので、構成が直感的です。いくつか例を挙げると、次の表のようになります。

ファイルの場所対応する URL
app/page.tsx/
app/about/page.tsx/about
app/blog/page.tsx/blog
app/blog/first/page.tsx/blog/first

ここで注意したいのは、ページとして表示されるのは page.tsx という名前のファイルだけという点です。同じフォルダに Button.tsx のような別のコンポーネントを置いても、それが URL になることはありません。フォルダに page.tsx が無ければ、そのパスはページとして存在しない扱いになります。

layout.tsx で共通の枠を作る

ヘッダーやフッターのように、全ページで共通の見た目を layout.tsx にまとめられます。app/layout.tsx はすべてのページを包む「一番外側の枠」です。App Router では、このルートレイアウトは必須で、htmlbody タグをここに書きます。

app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body>
        <header>共通ヘッダー</header>
        {children}
        <footer>共通フッター</footer>
      </body>
    </html>
  );
}

children の位置に、各ページの page.tsx の内容が差し込まれます。つまり、どのページを開いてもヘッダーとフッターは共通で表示され、真ん中だけがページごとに切り替わります。特定のフォルダ内だけで共通にしたいレイアウトは、そのフォルダに layout.tsx を置けば、その配下のページにだけ適用されます。

Link コンポーネントでページを移動する

ページ間の移動には、next/link<Link> コンポーネントを使います。通常の <a> タグでもリンクはできますが、<Link> を使うとページ全体を再読み込みせずに切り替わるため、表示が速く、入力中の状態なども保たれます。

app/page.tsx
import Link from 'next/link';

export default function Home() {
  return (
    <nav>
      <Link href="/">ホーム</Link>
      <Link href="/about">会社概要</Link>
      <Link href="/blog">ブログ</Link>
    </nav>
  );
}

href に移動先の URL を指定するだけです。書き方は <a> とほとんど同じですが、内部リンクには <Link> を使うのが Next.js の基本と覚えておきましょう。外部サイトへのリンクは、これまでどおり <a> で問題ありません。

[id] で動的なページを作る

ブログ記事のように「URL の一部が可変」なページは、フォルダ名を [ ](角括弧)で囲んで作ります。たとえば app/blog/[id]/page.tsx と置くと、/blog/1/blog/hello など、/blog/ に続く任意の値を1つのページで受け取れます。この可変部分は params から取り出します。

app/blog/[id]/page.tsx
export default async function BlogPost({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;

  return (
    <main>
      <h1>記事ID: {id}</h1>
    </main>
  );
}

フォルダ名 [id]id が、そのまま params のプロパティ名になります。/blog/5 にアクセスすれば id'5' になり、この値をもとにデータベースや API から該当記事を取得する、という使い方が一般的です。なお Next.js 15 以降では params が Promise になったため、上のように await で受け取ります(それ以前のバージョンでは直接 params.id と書けます)。

ページが表示されないとき

作ったはずのページが 404 になる場合、いくつか定番の原因があります。まず確認したいのがファイル名です。ページになるのは page.tsx という決まった名前だけで、index.tsxPage.tsx(大文字始まり)ではページとして認識されません。App Router では index ではなく page である点に注意してください。

次に多いのがフォルダの場所です。ページ用のフォルダは必ず app の中に置きます。app の外に作っても URL にはなりません。また、コンポーネントを export default で書き出しているかも確認しましょう。名前付きエクスポートだけだと、Next.js がページとして読み込めずエラーになります。

まとめ

Next.js の App Router では、app ディレクトリにフォルダを作り、その中に page.tsx を置くだけでページが作られます。フォルダ名がそのまま URL になり、共通の枠は layout.tsx、ページ間の移動は <Link>、URL の一部が可変なページは [id] フォルダで実現します。ページが表示されないときは、ファイル名が page.tsx か、app の中に置いているか、export default しているかを確認しましょう。この基本さえ押さえれば、複数ページのサイトを素早く組み立てられます。

参考ページ