Contents
Vue Router の基本構成と単体利用時の設定方法
Vue 3 アプリにおいて、router/index.ts にすべてのルート情報を記述する方式は最もベーシックなパターンです。ここで定義した URL 構造やヒストリーモードが、ページ遷移全体の挙動を決定します。本節では TypeScript と組み合わせた実装例と、型安全を保つポイントを解説します。
router/index.ts におけるルート定義とインスタンス生成
以下は Vue Router 4(Vue 3 向け)で推奨されている記述です。createRouter と createWebHistory を組み合わせ、routes 配列に各ページコンポーネントをオブジェクト形式で登録します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// src/router/index.ts import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' import HomeView from '@/views/HomeView.vue' const routes: Array<RouteRecordRaw> = [ { path: '/', name: 'home', component: HomeView, meta: { title: 'ホーム' } }, { path: '/about', name: 'about', // 遅延ロードで初回バンドルを軽減 component: () => import('@/views/AboutView.vue') }, { path: '/user/:id', name: 'user-detail', component: () => import('@/views/UserDetail.vue'), props: true // :id をコンポーネントの prop に自動マッピング } ] export const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes, scrollBehavior(to, from, savedPosition) { return savedPosition ?? { top: 0 } } }) |
RouteRecordRawが提供する型情報により、パス文字列とコンポーネントの不整合は開発時に検出できます。props: trueを設定すると、動的セグメント(:id)が自動でpropsに変換されるため、受け側コンポーネントではシンプルに型定義でき、テストもしやすくなります。
明示的管理のメリットと注意点
Vue Router 単体利用は「コードベースでルートを一元管理」できる点が特徴です。小規模〜中規模 SPA では設定ファイルが増えても可読性を保ちやすく、ガード関数やリダイレクトといった高度なロジックを自由に組み込めます。一方で ルート定義が散在すると見通しが悪くなる ため、ファイル構成や命名規則を統一しておくことが重要です。
Nuxt 3 に組み込まれた Vue Router の自動生成機能
Nuxt 3(v3.13 以降)では pages ディレクトリ を走査し、ファイル構造から Vue Router 用の routes オブジェクトを自動的に生成します。開発者はページコンポーネントを作成するだけでルーティングが有効になるため、設定コードが不要になり、保守コストが大幅に削減されます(公式ドキュメント: https://nuxt.com/docs/api/routing/pages)。
ファイルベースルーティングの基本概念
pages/ 配下の .vue ファイル名とフォルダ階層が URL パスに直結します。以下は典型的な構成例です。
|
1 2 3 4 5 6 7 8 9 |
pages/ ├─ index.vue // → / ├─ about.vue // → /about ├─ user/ │ ├─ [id].vue // → /user/:id (必須の動的セグメント) │ └─ [[slug]].vue // → /user/ と /user/:slug の両方にマッチ └─ admin/ └─ settings.vue // → /admin/settings |
[]で囲んだ部分は 必須の動的パラメータ、[[]](二重括弧)は 省略可能なセグメント として扱われます。- フォルダ階層そのものが子ルートになるため、
children配列を書かずに入れ子構造を表現できます。
Nuxt の自動生成と開発体験の関係
ファイルを追加・削除すると即座に routes が再計算され、Vite が提供する Hot Module Replacement(HMR)によってブラウザがリロードなしで反映されます。これにより 「コードを書くだけ」 という感覚でルーティングが完成し、特に大規模プロジェクトでのディレクトリ構造変更がシームレスになります。
ネスト・動的・グループ化の実装比較
Vue Router と Nuxt 3 は同等の機能を提供しますが、記述方法と保守性に違いがあります。ここでは children 配列(Vue Router)と フォルダ階層(Nuxt)、さらに「グループ化」に相当するテクニックについて比較します。
Vue Router の children 配列で表す入れ子ルート
children プロパティにサブルートオブジェクトを並べると、階層的な UI(例: ダッシュボード内タブ)をコード上で明示的に管理できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// router/index.ts の一部 { path: '/admin', component: () => import('@/layouts/AdminLayout.vue'), children: [ { path: 'users', name: 'admin-users', component: () => import('@/pages/admin/Users.vue') }, { path: 'settings', name: 'admin-settings', component: () => import('@/pages/admin/Settings.vue') } ] } |
pathが相対パスで書かれる点に注意が必要です('users'は最終的に/admin/usersに解決されます)。- 階層が深くなると routes 配列の肥大化 が起こりやすく、可読性が低下しがちです。
Nuxt のフォルダ階層で表現するネストされたページ
Nuxt ではフォルダ構造そのものが子ルートになるため、追加や削除はファイル操作だけで完了します。レイアウトとの組み合わせもシンプルです。
|
1 2 3 4 |
// pages/admin/ // ├─ users.vue // → /admin/users // └─ settings.vue // → /admin/settings |
- 共通レイアウトを利用したい場合は
layouts/admin.vueを作成し、ページ側では<slot />で差し込みます。 - ディレクトリ構造が URL と一致するため、新規メンバーでも全体像を直感的に把握できます。
動的パラメータの表記比較
| 項目 | Vue Router (単体) | Nuxt 3 |
|---|---|---|
| 必須動的セグメント | path: '/user/:id' |
pages/user/[id].vue |
| 任意(省略可能) | カスタムガードで条件分岐が必要 | pages/user/[[slug]].vue が自動マッチ |
| 型安全のヒント | props: true + TypeScript インターフェース |
Typed Pages が自動生成する型 (UserPageProps) |
Nuxt の動的ページ例
|
1 2 3 4 5 6 7 8 9 |
<!-- pages/user/[id].vue --> <script setup lang="ts"> defineProps<{ id: string }>() </script> <template> <h1>User ID: {{ id }}</h1> </template> |
- Typed Pages(v3.5+)により
propsの型が自動推論され、IDE が補完とエラー検出を行います。
グループ化の代替手段
公式ドキュメントには「routeGroup」なる機能は記載されていません。Nuxt で似たような用途を実現したい場合は meta フィールド や カスタムミドルウェア を活用します。
|
1 2 3 4 5 6 7 8 9 |
// pages/admin/settings.vue <script setup lang="ts"> definePageMeta({ // 任意のキーでグループ情報を保持 routeGroup: 'admin', middleware: ['auth'] }) </script> |
routeGroupは任意の文字列として扱えるだけで、フレームワーク側が自動的に処理するわけではありません。- 同一グループのページに対して共通ミドルウェアやレイアウトを適用したい場合は、layout と middleware ディレクトリ の組み合わせで実装します。
型安全とマッチングロジックの違い
大規模開発では型安全がバグ防止に直結します。Vue Router と Nuxt 3 はそれぞれ異なるアプローチで型情報を提供しています。
Typed Pages(Nuxt 3.5+)による自動型生成
pages/ 配下のファイルはビルド時に nuxt/types/pages.d.ts が生成され、ページコンポーネントの props や route.params の型 が自動的に推論されます。
|
1 2 3 4 5 6 |
// pages/blog/[slug].vue <script setup lang="ts"> const route = useRoute() type Params = typeof route.params // { slug: string } </script> |
route.params.slugが必ず文字列であることがコンパイル時に保証され、ランタイムエラーを未然に防げます。definePageMetaに記述したカスタムキーも同様に型付けできるため、プロジェクト全体で一貫したインターフェースを保てます。
Vue Router の Path Parser と Path Ranker
Vue Router は内部的に Path Parser(文字列 → トークン変換)と Path Ranker(マッチ度スコアリング)を組み合わせ、最適なルートを高速に選択します。公式リポジトリの実装は O(N) の計算量で動的セグメントや正規表現パターンを処理できるよう設計されています。
|
1 2 3 4 |
// コンセプト的なフロー(内部実装例) parse('/user/123') // → ['user', ':id'] rank(['user/:id'], '/user/123') // スコア 1.0 (完全一致) |
- 手動で定義した
routes配列がそのまま入力になるため、開発者が意図しないマッチング が起きた場合はルート定義を見直す必要があります。 - Nuxt はこのアルゴリズムに自動生成されたページ情報を流し込むだけなので、個別にチューニングする機会は少なくなります。
SSR/SEO 効果・開発体験・移行シナリオ
Nuxt の SSR がもたらす SEO とパフォーマンス向上
Nuxt 3 はデフォルトで サーバーサイドレンダリング(SSR) を提供し、ページロード時に完全な HTML が生成されます。検索エンジンは JavaScript 実行なしでコンテンツを取得できるため、メタタグや OG 情報が正しくインデックス されやすくなります。
|
1 2 3 4 5 6 7 8 9 |
// pages/blog/[slug].vue <script setup lang="ts"> definePageMeta({ title: (route) => `記事:${route.params.slug}`, // 静的生成(SSG)を有効にするフラグ prerender: true }) </script> |
prerender: trueを設定すると、ビルド時に対象ページが 静的 HTML として出力され CDN キャッシュが容易になります。- Nuxt は自動で
<link rel="prefetch">や<meta>タグを生成し、ファーストビューの高速化と SEO 効果を同時に実現します。
auto‑import・Hot Reload・Static Generate の比較
| 項目 | Vue Router(単体) | Nuxt 3 |
|---|---|---|
| auto‑import | 手動 import が必須 |
pages/, components/ から自動インポート |
| Hot Reload | Vite のみだが、ページ追加時は手動リロードが必要になるケースあり | Nuxt dev server がページ・レイアウト変更を即時反映 |
| 静的サイト生成 | vite build 後に別プラグイン(例: prerender-spa-plugin)で対応 |
nitro が全ルートの HTML を自動生成し、nuxt generate だけで完結 |
- 開発者は「コードを書くだけ」で即座にプレビューでき、ビルド設定の負荷が大幅に削減されます。
既存 Vue Router プロジェクトを Nuxt 3 に移行する手順
- プロジェクト構造の整理
src/router→pages/配下へページコンポーネントを移動し、router/index.tsは削除。- 動的ルートの変換
path: '/user/:id'→pages/user/[id].vueにリネームし、defineProps<{ id: string }>()を追加。- メタ情報・ガードの移植
meta.titleはdefinePageMeta({ title: '...' })に置き換える。- カスタムナビゲーションガードは
defineNuxtRouteMiddlewareへ変換し、middleware/ディレクトリに配置。 - レイアウトの統合
- 共通ヘッダー・フッターは
layouts/default.vueに集約し、ページ側では<slot />のみ残す。 - SSR 対応の確認
- クライアントサイド専用 API 呼び出しは
useAsyncDataやuseFetchへ置き換え、サーバーでも安全に実行できるかテストする。
移行時の注意点
- プラグイン互換性:Vue Router 用に書いたプラグインは Nuxt のプラグイン形式(
plugins/ディレクトリ)へ移植が必要です。 - 環境変数:
import.meta.env.BASE_URLが自動で設定されるため、ハードコーディングされたベースパスは相対パスに書き換えてください。 - 型定義の更新:Typed Pages の恩恵を受けるには
nuxt/types/pages.d.tsをプロジェクトルートに含め、IDE が正しく認識できるように設定します。
記事のまとめ
| 項目 | Vue Router(単体) | Nuxt 3 |
|---|---|---|
| ルート定義方式 | router/index.ts に手動記述 |
pages/ のファイル構造から自動生成 |
| ネスト表現 | children 配列でコード管理 |
フォルダ階層がそのまま子ルートに |
| 動的パラメータ | パス文字列 :id、props: true で型付与 |
[id].vue / [[slug]].vue が自動マッチ |
| 型安全 | 手動でインターフェースを作成 | Typed Pages が自動生成し IDE 補完が可能 |
| SSR/SEO | 必要に応じて手動設定(例: vite-plugin-ssr) | デフォルトで SSR、meta・prefetch 自動生成 |
| 開発体験 | 手動インポートとビルド設定が必要 | auto‑import、Hot Reload、Static Generate が標準装備 |
Vue Router 単体は 細かい制御 が可能で、カスタムガードや特殊マッチングを柔軟に書ける点が強みです。一方、Nuxt 3 は ファイルベースルーティングと SSR の自動化 により、生産性・保守性・SEO 効果の面で大きくリードしています。プロジェクト規模やチーム体制、検索エンジン最適化の要件を踏まえて、どちらのアプローチが最適か検討してください。