Unplugin Vue Routerとは
Unplugin Vue Routerとは、一言で言うとVue.jsプロジェクトにおいて型安全性の高いファイルベースルーティングを実現するためのプラグインです。
また、今回は取り上げませんがその他の機能として、実験的なデータローダー機能をサポートしています。
なぜUnplugin Vue Routerを調べてみたのか
Vue.jsのフレームワークであるNuxt.jsの主要なメリットとして、レンダリング方式の柔軟な切り替えなどと並んで、ファイルベースルーティングによる開発効率の向上がよく挙げられます。
私自身試してみたこともあり、直感的で分かりやすいと感じておりました。
しかし、私が携わるプロジェクトは比較的小規模なものが多く、Nuxt.jsの豊富な機能セットはいささか過剰であると判断し、その採用を見送ってきました。
そんな中、Nuxt.jsと同様のファイルベースルーティングを単独の機能として追加できるUnplugin Vue Routerを知り、これならば小規模プロジェクトにも適しているのでは考え、まずは試してみることにしました。
実際に試してみた
セットアップ手順
実際にリファレンスに沿って設定してみます。
プロジェクト作成
まずはcreate-viteでテンプレートを使ってさくっとプロジェクトを作成します。
筆者はVue.js+TypeScript+Viteでの作業が主なので今回はそのまま使ってます
$ create-vite
✔ Project name: … vite-project
✔ Select a framework: › Vue
✔ Select a variant: › TypeScript
Scaffolding project in /xxx/vite-project...
Done. Now run:
cd vite-project
npm install
npm run dev
作成されたプロジェクトで任意のパッケージマネージャを使用して、node_modulesをインストール、開発サーバーを起動してみると以下の画面が表示されるはずです。
ライブラリインストール
ここで今回の主役であるvue-router
とunplugin-vue-router
をインストールします。
$ yarn add vue-router
$ yarn add -D unplugin-vue-router
プラグインの追加
バンドルに今回のプラグインを含めるよう設定を変更します。
import { defineConfig } from 'vite'
+import VueRouter from 'unplugin-vue-router/vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
+ VueRouter(),
vue()
],
})
設定が変更できたらここでもう一度開発サーバーを起動してみましょう。
rootディレクトリにtyped-router.d.ts
が作成されていれば成功です。
ここまでできたらtsconfig.json
を編集し、unplugin-vue-routerの型を追加しておきましょう。
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
+ "types": ["unplugin-vue-router/auto-routes"]
},
- "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "./typed-router.d.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
ここまででセットアップは完了です。
基本的な使用方法
アプリケーションへの反映
main.tsでVue Routerの取り込みを行い、アプリケーションへ反映します。
これはいつものVue Routerと同じですね
import { createApp } from 'vue'
import './style.css'
+import { createRouter, createWebHistory } from 'vue-router'
+import { routes } from 'vue-router/auto-routes'
import App from './App.vue'
+const router = createRouter({
+ history: createWebHistory(),
+ routes,
+ })
-createApp(App).mount('#app')
+createApp(App).use(router).mount('#app')
App.vueでいつものようにRouterViewを表示するように設定します。
<script setup lang="ts">
import { RouterView } from 'vue-router'
</script>
<template>
<RouterView />
</template>
これで反映の準備が整いました。
ファイルの配置=ルーティング
次に/src
配下にpages
ディレクトリを作成し、その中にindex.vue
を作成します。
<script setup lang="ts">
import { RouterLink } from 'vue-router'
</script>
<template>
<h1>Home</h1>
<p>URL: {{ $route.path }}</p>
<RouterLink to="/Hello">to Hello</RouterLink>
</template>
このファイルがhttps://www.hogehoge.com/
の際にルーティングされるファイルです
遷移先のHello.vueも同じディレクトリに作成しておきます。
<script setup lang="ts">
import { RouterLink } from 'vue-router'
</script>
<template>
<h1>Hello</h1>
<p>URL: {{ $route.path }}</p>
<RouterLink to="/">to Home</RouterLink>
</template>
作成できたらこの状態でまた開発サーバーを起動してみましょう。
Vue Routerの設定ファイルを作成していないのにしっかり画面遷移が行われています。
これはかなり楽ですね。
さらに階層をネストさせたい場合
例えば先ほどのhelloの下にworldをつけて"/hello/world"で別の画面を表示したい場合は、
pages
ディレクトリの中にhello
ディレクトリを作成、その中にhello.vue
を移動させ、名前をindex.vue
にすることで現在と同様の挙動を得られます。
そして、同階層にWorld.vue
を先ほどまでと同じ手順で作成します。
発展:動的ルーティング
[]でファイル名を囲むことでパスのパラメータを動的に変更することができます。
pagesディレクトリ配下に[id].vueを作成してみます。
<script setup lang="ts">
import { RouterLink } from 'vue-router'
import { useRoute } from 'vue-router'
const id = useRoute().params.id
</script>
<template>
<h1>{{ id }}</h1>
<p>URL: {{ $route.path }}</p>
<RouterLink to="/">to Home</RouterLink>
</template>
この時点ではまだ、[id].vueのパスは決まっておらず、idとして渡された値に応じてパスが動的に作成されます。
pages/index.vueに自由入力欄を設けて動的にパスを作成してみます。
<script setup lang="ts">
import { RouterLink } from 'vue-router'
+import { ref } from 'vue'
+const id = ref('')
</script>
<template>
<h1>Home</h1>
<p>URL: {{ $route.path }}</p>
<RouterLink to="/Hello">to Hello</RouterLink><br>
+ <input type="text" v-model="id" /><br>
+ <RouterLink :to="`/${id}`">to {{ id }}</RouterLink>
</template>
実際に試してみて分かったUnplugin Vue Router
開発効率の向上
やはりファイルベースルーティングは直感的で分かりやすく、型補完が効くこともあり認知負荷が軽減されミスを最小限に抑えることができそうです。
従来のルーティング方法だとページを追加するたびに下記のようなルーティングの設定ファイルを更新していましたが、そこがなくなるのはストレスフリーですね。
// Components
import SignIn from "@/views/SignIn.vue";
import DashBoard from "@/views/DashBoard.vue";
import DeviceList from "@/views/DeviceList.vue";
import Schedule from "@/views/Schedule.vue";
import Alerts from "@/views/Alerts.vue";
import AlertsLog from "@/views/AlertsLog.vue";
import UserList from "@/views/UserList.vue";
// Router Rules
const routes: RouteRecordRaw[] = [
{
path: "/signin",
name: "signin",
component: SignIn,
meta: { requiredAuth: false },
},
{
path: "/dashboard",
name: "dashboard",
component: DashBoard,
meta: { requiredAuth: true },
children: [
{
path: "home",
name: "home",
component: DeviceList,
meta: { requiredAuth: true },
},
{
path: "Schedule",
name: "Schedule",
component: Schedule,
meta: { requiredAuth: true },
},
{
path: "Alerts",
name: "Alerts",
component: Alerts,
meta: { requiredAuth: true },
},
{
path: "AlertsLog",
name: "AlertsLog",
component: AlertsLog,
meta: { requiredAuth: true },
},
{
path: "UserList",
name: "UserList",
component: UserList,
meta: { requiredAuth: true },
},
],
},
{
path: "/:pathMatch(.*)*",
redirect: {
name: "signin",
},
},
];
私のようにNuxt.jsを採用するほどでもないが、ファイルベースルーティングでケアレスミスを減らしたい方は検討してみても良いかもしれません。