404 Not Found

404 Not Found


nginx

ページとルーティング

BobはMegaShopに商品詳細ページを追加する際, 50のvue-routerルートを手動設定しました。新商品が出品されるたびにルートファイルを編集する必要があり, 非常に面倒でした。CharlieはNuxt 3がファイル規約に基づいてルートを自動生成することを教えました。ファイルを作成するだけでルートが作成されます。

1. 学ぶ内容


2. 管理者の実話

(1) ペインポイント:手動ルーティング設定の悪夢

Bobは従来のVue Routerを使ってMegaShopに1,000のルートを設定しました。各カテゴリと各商品ページに1つずつです。新商品が出品されるたびにルートファイルを編集する必要があり, 1つでも忘れると404エラーになりました。Aliceは商品を見つけられず, クレーム率が急増しました。

(2) Nuxtファイルルーティングによる解決策

Nuxt 3のファイルベースルーティングでは, Bobはファイルを作成するだけです:

TEXT
pages/products/[id].vue  →  /products/:id

100万商品が1つのファイルで済み, 動的パラメータは自動的に渡されます。

(3) 効果:ゼロ設定ルーティング

Bobはもうルート設定を書く必要がありません。新しいページの追加は新しいファイルを作成するだけで済み, 100万商品の詳細ページもたった1つの[id].vueで対応できます。


3. ファイルルーティングルール

(1) ディレクトリからルートへのマッピングプロセス

100%
flowchart LR
    A[pages/index.vue] -->|"/"| B[ルートルート]
    C[pages/about.vue] -->|"/about"| C2[Aboutルート]
    D[pages/products/index.vue] -->|"/products"| D2[商品一覧ルート]
    E[pages/products/[id].vue] -->|"/products/:id"| E2[商品詳細ルート]
    F[pages/categories/[...slug].vue] -->|"/categories/:slug*"| F2[キャッチオールルート]

(2) ファイルルーティングマッピングルール

ファイルパス 生成されるルート 説明
pages/index.vue / ホーム
pages/about.vue /about 静的ページ
pages/products/index.vue /products 商品一覧
pages/products/[id].vue /products/:id 動的パラメータ
pages/categories/[slug].vue /categories/:slug 動的パラメータ
pages/categories/[...slug].vue /categories/:slug(*) ワイルドカードルート
pages/404.vue /404 カスタム404

(1) ▶ サンプル:基本ページルーティング

VUE
<!-- pages/index.vue -->
<template>
  <div>
    <h1>MegaShop - 数百万の商品</h1>
    <NuxtLink to="/products">商品を閲覧</NuxtLink>
  </div>
</template>

出力:

TEXT
// 実行成功
VUE
<!-- pages/about.vue -->
<template>
  <div>
    <h1>MegaShopについて</h1>
    <p>世界中に100万以上の商品をお届け</p>
  </div>
</template>

4. 動的ルーティング

(1) 単一パラメータの動的ルーティング

[param]構文を使って動的ルーティングパラメータを定義します。

(1) ▶ サンプル:商品詳細ページの動的ルーティング

VUE
<!-- pages/products/[id].vue -->
<template>
  <div>
    <h1>商品 #{{ route.params.id }}</h1>
    <p>価格: ${{ product?.price }} USD</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
</script>

出力:

TEXT
// 実行成功

(2) ワイルドカードルート

[...slug]構文を使って多段パスをキャプチャします。

(2) ▶ サンプル:多段カテゴリワイルドカードルーティング

VUE
<!-- pages/categories/[...slug].vue -->
<template>
  <div>
    <h1>カテゴリ: {{ slugPath }}</h1>
    <p>{{ products.length }} 件の商品が見つかりました</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
// /categories/electronics/headphones → slug = ['electronics', 'headphones']
const slugPath = computed(() => (route.params.slug as string[]).join('/'))
const { data: products } = await useFetch(`/api/categories/${slugPath.value}`)
</script>

出力:

TEXT
// 実行成功

(3) 動的ルーティングパラメータの型

構文 マッチ URLの例 paramsの値
[id] 単一セグメント /products/123 { id: '123' }
[id].vue + index.vue オプション /products または /products/123 { id?: '123' }
[...slug] 複数セグメントワイルドカード /a/b/c { slug: ['a','b','c'] }

5. ネストルート

(1) ネストルーティング構造

ネストルーティングには親ページ (同名の.vueファイル)と子ディレクトリの組み合わせが必要です:

TEXT
pages/
├── products/
│   ├── index.vue          # /products (子)
│   ├── [id].vue           # /products/:id (子)
│   └── edit.vue           # /products/edit (子)
└── products.vue           # /products (親, <NuxtPage />を持つ)

(1) ▶ サンプル:商品ページのネストルート

VUE
<!-- pages/products.vue - 親レイアウト -->
<template>
  <div>
    <nav class="product-nav">
      <NuxtLink to="/products">全商品</NuxtLink>
      <NuxtLink to="/products/featured">注目商品</NuxtLink>
    </nav>
    <!-- 子ルートはここにレンダリング -->
    <NuxtPage />
  </div>
</template>

出力:

TEXT
// 実行成功
VUE
<!-- pages/products/index.vue - 子:商品一覧 -->
<template>
  <div>
    <h1>全商品</h1>
    <p>100万商品がご利用いただけます</p>
  </div>
</template>
VUE
<!-- pages/products/[id].vue - 子:商品詳細 -->
<template>
  <div>
    <h1>商品詳細</h1>
    <p>ID: {{ route.params.id }}</p>
  </div>
</template>

(2) ネストルートとレイアウトの比較

項目 ネストルーティング レイアウト
仕組み 親ページ + NuxtPageスロット layouts/ + NuxtLayout
ルーティング関係 親子ルートがレイアウトを共有 ページレベルのレイアウト切替
データ取得 親と子がそれぞれuseFetchを使用 レイアウトはデータを取得しない
ユースケース カテゴリ → 商品 → レビューの階層 全体的なページレイアウト (ヘッダー/フッター)

6. プログラマティックナビゲーション

(1) 3つのナビゲーション方法の比較

API 目的 サーバー側で利用可能 ユースケース
navigateTo() プログラマティックナビゲーション ログイン後のリダイレクト
useRouter().push() クライアント側ナビゲーション ボタンクリックでのナビゲーション
NuxtLink 宣言的リンク テンプレート内のナビゲーション

(1) ▶ サンプル:navigateToサーバー側リダイレクト

TYPESCRIPT
// ミドルウェアまたはサーバー側コンテキスト内
export default defineNuxtRouteMiddleware((to) => {
  const isAuthenticated = useState('isAuthenticated')

  if (!isAuthenticated.value && to.path.startsWith('/admin')) {
    return navigateTo('/login', { redirectCode: 302 })
  }
})

出力:

TEXT
// 実行成功

(2) ▶ サンプル:useRouterクライアント側ナビゲーション

VUE
<template>
  <button @click="goToProduct(product.id)">
    詳細を見る
  </button>
</template>

<script setup lang="ts">
const router = useRouter()

function goToProduct(id: number) {
  router.push(`/products/${id}`)
}
</script>

出力:

TEXT
// 実行成功

(3) ▶ サンプル:useRouteでパラメータを取得

VUE
<script setup lang="ts">
const route = useRoute()

// パラメータにアクセス
const productId = route.params.id         // [id].vueから
const categorySlug = route.params.slug     // [...slug].vueから

// クエリパラメータにアクセス
// /products?category=electronics&sort=price
const category = route.query.category      // 'electronics'
const sort = route.query.sort              // 'price'
</script>

出力:

TEXT
// 実行成功

7. MegaShop多段ルーティングのハンズオンガイド

(1) MegaShopルーティングプラン

URL ファイル 機能
/ pages/index.vue ホーム
/products pages/products/index.vue 商品一覧
/products/[id] pages/products/[id].vue 商品詳細
/categories/[category] pages/categories/[category].vue カテゴリページ
/categories/[category]/[subcategory] pages/categories/[...slug].vue サブカテゴリ
/cart pages/cart.vue ショッピングカート
/checkout pages/checkout.vue チェックアウト
/admin pages/admin/index.vue 管理ダッシュボード
/admin/products pages/admin/products/index.vue 商品管理
/404 pages/404.vue 404ページ

(1) ▶ サンプル:MegaShop 404ページ

VUE
<!-- pages/404.vue -->
<template>
  <div class="not-found">
    <h1>404 - 商品が見つかりません</h1>
    <p>お探しの商品は存在しません。</p>
    <NuxtLink to="/products">全商品を閲覧</NuxtLink>
  </div>
</template>

出力:

TEXT
// 実行成功

8. 総合例:MegaShopルーティングシステム

VUE
<!-- pages/index.vue - ホームページ -->
<template>
  <div>
    <section class="hero">
      <h1>MegaShop</h1>
      <p>100万以上の商品を世界中にお届け</p>
      <NuxtLink to="/products">今すぐショッピング</NuxtLink>
    </section>
    <section class="featured">
      <ProductCard v-for="p in featured" :key="p.id" :product="p" />
    </section>
  </div>
</template>

<script setup lang="ts">
const { data: featured } = await useFetch('/api/products/featured')
</script>
VUE
<!-- pages/products/[id].vue - 商品詳細 -->
<template>
  <div v-if="product">
    <h1>{{ product.name }}</h1>
    <p class="price">${{ product.price }} USD</p>
    <button @click="addToCart">カートに追加</button>
    <button @click="goBack">一覧に戻る</button>
  </div>
  <div v-else>
    <p>商品が見つかりません</p>
    <NuxtLink to="/products">商品を閲覧</NuxtLink>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const router = useRouter()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

function addToCart() {
  navigateTo('/cart')
}

function goBack() {
  router.back()
}
</script>

❓ よくある質問

Q 動的ルーティングのパラメータは文字列ですか, 数値ですか?
A URLパラメータは常に文字列です。数値が必要な場合は手動で変換してください:Number(route.params.id)。またはuseFetch使用時にAPIの戻り値の型で決定します。
Q [id].vueと[...slug].vueの違いは何ですか?
A [id]は単一のパスセグメントのみマッチします (/products/123)。[...slug]は複数セグメントのパスをマッチします (/a/b/c)。slugは配列になります。キャッチオールルートは階層が無制限のカテゴリに適しています。
Q ネストルートの親ページは必須ですか?
A はい。親ページproducts.vueとサブディレクトリproducts/の両方が存在して初めてネストルートが形成されます。子ルートのみが必要な場合は, 親ページを作成しないでください。
Q NuxtLinkと通常のaタグの違いは何ですか?
A NuxtLinkはクライアント側ナビゲーションに使用されます (ページをリフレッシュしない)。aタグはフルページリフレッシュを引き起こします。内部ナビゲーションにはNuxtLinkを, 外部リンクにはaタグを使用してください。
Q カスタム404ページの設定方法は?
A pages/404.vueファイルを作成するだけです。Nuxt 3はルートがマッチしない場合に自動的にこのページを表示します。キャッチオールルートで処理することも可能です。
Q routeRulesとルーティングの関係は何ですか?
A routeRulesnuxt.config.tsで設定し, ルートパスに基づいてレンダリング戦略 (SSR/ISR/CSR)を指定します。ルートの定義には影響しません。ルートはpages/ディレクトリのファイルで定義され, routeRulesはレンダリング動作のみを制御します。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度:⭐):pages/about.vueとpages/contact.vueを作成し, ルートが自動生成されることを検証してください。
  2. 応用問題 (難易度:⭐⭐):/products/[category]/[id]の2段動的ルーティングを実装し, ページ上に「カテゴリ」と「id」パラメータを表示してください。
  3. チャレンジ (難易度:⭐⭐⭐):キャッチオールルート[...slug].vueを実装し, /docs/getting-started/installationのような多段パスをレンダリングし, パンくずナビゲーションバーを表示してください。

---|

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%