Unplugin Vue Router is a plugin for Vue.js that allows you to automatically generate file-based routing.
File-based routing is a pattern that automates route generation based on your project’s directory structure.
This means that the folder and file structure directly reflects your application’s navigation. This eliminates the need to manually maintain route configuration files.
It’s similar to how frameworks like Nuxt.js or Next.js work, but without needing to use a meta-framework.
Basic Installation and Configuration
To install Unplugin Vue Router in our project (which already has Vue Router installed) we do the following.
npm install unplugin-vue-router --save-dev
Now to configure it
Add the plugin to the Vite configuration in vite.config.ts
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
import VueRouter from 'unplugin-vue-router/vite'
export default defineConfig({
plugins: [
VueRouter({
routesFolder: 'src/pages', // Routes folder
}),
Vue(), // Important: Vue() must come after!
],
})
Now we initialize the plugin in main.ts (or equivalent),
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router/auto' // Auto-imports the routes
const router = createRouter({
history: createWebHistory(),
// Routes are generated automatically!
})
const app = createApp(App)
app.use(router)
app.mount('#app')
Unplugin Vue Router maintains compatibility with Vue Router. It’s not a replacement, but an extension.
Basic File Structure
Routes are generated automatically following simple conventions. For example,
src/ └── pages/ ├── index.vue # → / ├── contact.vue # → /contact └── about.vue # → /about
In this case
- The route / would take you to the
index.vuecomponent - The route /contact would take you to the
contact.vuecomponent - The route /about would take you to the
about.vuecomponent
That easy 😉.
Nested Routes
Create subdirectories for nested routes. Each subdirectory inside /pages creates a new segment in the route. For example,
src/ └── pages/ ├── welcome.vue # → /welcome └── dashboard/ ├── settings.vue # → /dashboard/settings └── profile.vue # → /dashboard/profile
In this case,
- The route /welcome will take you to
welcome.vue - The route /dashboard/settings will take you to
dashboard/settings.vue - The route /dashboard/profile will take you to
dashboard/profile.vue
The Special Case of Index in Routes
You’ve seen that index has a somewhat special behavior. This file represents the base route of its directory. With this structure:
src/ └── pages/ ├── index.vue # → / └── dashboard/ └── index.vue # → /dashboard
- The route / will take you to
index.vue - The route /dashboard will take you to
dashboard/index.vue
This is very common behavior in routing, file servers, etc.
Dynamic Routes and Parameters
For dynamic routes and parameters, Unplugin Vue Router uses brackets as placeholders for parameters,
[param].vue→ Dynamic route (e.g.,/users/123)
That is, the following folder structure
src/ └── pages/ └── users/ ├── [id].vue # → /users/
In this example, routes for the user system will be automatically generated:
users/index.vue→ Route/users(user list).users/[id].vue→ Dynamic route/users/:id(details of a specific user).
You can use parameters in both file names and folders, and combine them at any nesting level to create the routes you need.
Accessing Parameters
We can access parameters in the same way we would normally do with Vue Router. For example, for pages/users/[id].vue
<script setup lang="ts">
const route = useRoute('/users/[id]')
console.log(route.params.id) // Type inferred as string
</script>
Type Safety
The plugin generates TypeScript types for all routes in typed-router.d.ts, providing autocompletion and validation.
router.push('/users/123') // Autocompletion and validation
const { id } = route.params // Inferred type: `id: string`
Catch-All Routes
For routes that need to capture multiple URL segments, we can use the [...slug].vue syntax,
[...slug].vue→ Catch-all route
That is, for example the structure:
src/ └── pages/ └── docs/ └── […slug].vue # → /docs/*
The slug parameter will be an array with all route segments.
- For example,
/docs/a/b/cwill capture['a', 'b', 'c']inparams.slug
not-found Page
To handle non-existent routes, create a [...not-found].vue file at the root of pages/. This will capture any undefined route and display your custom 404 page.
src/ └── pages/ └── […not-found].vue
- Any undefined URL (e.g.,
/non-existent/route) will display this component. - The URL segments are stored in
route.params.notFoundas an array.
Extending Routes Manually
We can also add additional routes, in case we need to customize any of them. To do this, we can edit the routes.ts file,
// src/routes.ts
import { extendRoutes } from 'unplugin-vue-router'
export default extendRoutes((routes) => {
routes.push({
path: '/custom',
component: () => import('./pages/custom.vue'),
meta: { requiresAuth: true }
})
})
