Vue Routerは、Vueの公式のルーティングライブラリです。URLに応じて表示するコンポーネントを切り替え、ページ全体を再読み込みせずに、複数の画面を持つ「シングルページアプリケーション(SPA)」を作れます。この記事では、Vue Router 4を前提に、導入から基本の設定、そして最もつまずきやすい「履歴モードとサーバー設定」までを整理します。
導入
新しく始めるなら、Vueの公式ツールcreate-vue(npm create vue@latest)がおすすめです。対話の中で、Vue Routerを含めるかを選べます。既存のプロジェクトに追加する場合は、Vue 3用のVue Router 4をインストールします。
# 新しく始めるなら:対話で「Vue Router」を選ぶと、最初から組み込まれる npm create vue@latest # 既存のプロジェクトに追加する場合(Vue 3 用は Vue Router 4) npm install vue-router@4
基本の設定
必要なのは、3つのファイルです。ルーターの定義、アプリへの組み込み、そしてルートのコンポーネントを表示する場所の用意です。
ルーターの定義
URLのパスと、表示するコンポーネントの対応を、routesの配列に書きます。createRouterのhistoryには、本番のアプリでは、createWebHistory()(履歴モード)か、createWebHashHistory()(ハッシュモード)を指定します。違いは、後の節で説明します。
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: About }
]
const router = createRouter({
// HTML5 の履歴モード。きれいな URL(/about)になる
// import.meta.env.BASE_URL は、サブフォルダに置くときの基準のパス(create-vue の既定の書き方)
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
export default router
アプリへの組み込み
Vueのプラグインと同じく、use()はmount()より前に呼びます。順序を逆にすると動きません。
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// use() は、mount() より前に呼ぶ
createApp(App).use(router).mount('#app')
RouterLinkとRouterView
<RouterView>は、現在のルートのコンポーネントを描画する場所です。リンクには、通常の<a>ではなく<RouterLink>を使います。公式が説明しているとおり、RouterLinkなら、ページを再読み込みせずにURLを変えられます。現在のページへのリンクには、router-link-exact-activeなどのクラスが自動で付くので、スタイルで強調できます。
<!-- src/App.vue -->
<template>
<nav>
<!-- <a> の代わりに RouterLink を使う:ページを再読み込みせずに、URL だけが変わる -->
<RouterLink to="/">Home</RouterLink>
<RouterLink :to="{ name: 'About' }">About</RouterLink>
</nav>
<!-- 現在のルートのコンポーネントが、ここに表示される -->
<RouterView />
</template>
<style scoped>
/* 現在のページのリンクには、自動でクラスが付く */
nav a.router-link-exact-active {
font-weight: bold;
}
</style>
パラメータの取得と、プログラムからの遷移
<script setup>では、useRoute()で現在のルート(パラメータやクエリ)を読み、useRouter()でルーター本体を取得して遷移させます。/user/:idのように、コロンで始まる部分が、URLによって変わるパラメータです。
<!-- src/views/UserDetail.vue -->
<script setup>
import { useRoute, useRouter } from 'vue-router'
const route = useRoute() // 現在のルート(パラメータやクエリを読む)
const router = useRouter() // ルーター本体(遷移させる)
// ルートの定義:{ path: '/user/:id', component: UserDetail }
// /user/123 を開いたとき、route.params.id は '123'(文字列)
function goHome() {
router.push('/') // プログラムから遷移する
}
</script>
<template>
<h1>ユーザー {{ route.params.id }}</h1>
<button type="button" @click="goHome">トップへ戻る</button>
</template>
ここでroute.params.idは、文字列で渡されます。また、/user/1から/user/2へ移動するときは、同じコンポーネントが再利用されるため、onMountedは再実行されません。詳しくはVue Routerで多階層のルート定義を整理する方法をご覧ください。
履歴モードで、直接アクセスが404になる理由
最もつまずきやすいのが、これです。開発中は動いたのに、本番のサーバーに置くと、トップページ以外のURL(/aboutなど)を直接開いたり、リロードしたりしたときに、404になることがあります。
原因は、履歴モードの仕組みです。createWebHistory()は、URLをきれいな形(/about)にしますが、サーバーから見ると、/aboutという名前のファイルは存在しません。公式の説明どおり、サーバーが、静的ファイル以外のすべてのパスにindex.htmlを返すように設定する必要があります。
nginxの場合
location / {
# ファイルやディレクトリが無ければ、index.html を返す
try_files $uri $uri/ /index.html;
}
Apacheの場合(.htaccess)
レンタルサーバーなどで使われるApacheでは、mod_rewriteで、実在しないパスをindex.htmlに渡します。
# .htaccess(Apache の場合)
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
# 実在するファイルやディレクトリでなければ、index.html に渡す
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
これらの例は、サイトのルートに置く前提です。サブフォルダに置く場合は、パスの基準を調整する必要があります。ルーター側はcreateWebHistory('/sub/')のように指定します(create-vueの既定のimport.meta.env.BASE_URLは、Viteのbase設定を反映します)。サーバー側も、書き換え先を合わせてください。
ハッシュモードという選択肢
サーバーの設定を変えられない場合は、createWebHashHistory()を使う方法があります。URLの#より後ろは、サーバーに送られないため、設定が不要です。ただし、公式も、SEOに悪い影響があると説明しています。検索から流入を得たいサイトでは、履歴モードをおすすめします。
存在しないURLは、404ページを用意する
履歴モードでは、サーバーが常にindex.htmlを返すため、存在しないURLでも、本物の404のステータスは返りません。アプリの側で、どのルートにも一致しなかったURLを受け止める、404用のルートを最後に置きます。
// routes の最後に置く:どのルートにも一致しなかった URL を受け止める
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('../views/NotFound.vue')
}
次のステップ
基本が分かったら、目的に応じて、次の機能に進んでください。
- ネストしたルート、動的ルート、404はVue Routerで多階層のルート定義を整理する方法
- ナビゲーションガードと
metaはルーティングの動的管理 - ログインの制御は認証付きルーティングを実装する方法
- 遷移中のローディングはページ遷移時にローディング画面を表示する方法
- ページごとのレイアウトはページごとに異なるレイアウトを切り替える方法
よくある質問(FAQ)
index.htmlを返す設定が必要です。nginxならtry_files、Apacheなら.htaccessのmod_rewriteで設定してください。設定できない場合は、ハッシュモードも選べます。RouterLinkは、ページを再読み込みせずに、URLを変えて画面を切り替えます。通常の<a>だと、ページ全体が再読み込みされ、SPAの利点が失われます。外部サイトへのリンクには、通常の<a>を使います。mount()より前にuse()で登録する必要があります。createApp(App).use(router).mount('#app')の順に書いてください。まとめ
Vue Routerは、ルートの定義、use(router)、<RouterLink>と<RouterView>の3点で、基本の画面切り替えが作れます。本番に置くときは、履歴モードに対応したサーバーの設定と、404ページの用意を忘れないようにしてください。

