Skip to content

Getting Started

Vue Router includes a built-in file-based routing plugin. It generates the routes and types automatically from your page components, so you no longer need to maintain a routes array manually.

Setup

Add the plugin to your bundler:

ts
import VueRouter from 'vue-router/vite'

export default defineConfig({
  plugins: [
    VueRouter({
      /* options */
    }),
    // ⚠️ Vue must be placed after VueRouter()
    Vue(),
  ],
})
ts
import VueRouter from 'vue-router/unplugin/rollup'

export default {
  plugins: [
    VueRouter({
      /* options */
    }),
    // ⚠️ Vue must be placed after VueRouter()
    Vue(),
  ],
}
ts
module.exports = {
  /* ... */
  plugins: [
    require('vue-router/unplugin/webpack')({
      /* options */
    }),
  ],
}
ts
module.exports = {
  configureWebpack: {
    plugins: [
      require('vue-router/unplugin/webpack')({
        /* options */
      }),
    ],
  },
}
ts
import { build } from 'esbuild'
import VueRouter from 'vue-router/unplugin/esbuild'

build({
  plugins: [VueRouter()],
})

After adding this plugin, start the dev server (usually npm run dev) to generate the first version of the types at typed-router.d.ts which should be added to your tsconfig.json along with "moduleResolution": "Bundler". This is what it should look like:

json
{
  "include": [
    // other files...
    "./typed-router.d.ts"
  ],
  "compilerOptions": {
    // ...
    "moduleResolution": "Bundler",
    // ...
  }
}
ts
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.

declare module 'vue-router/auto-routes' {
  import type {
    RouteRecordInfo,
    ParamValue,
    ParamValueOneOrMore,
    ParamValueZeroOrMore,
    ParamValueZeroOrOne,
  } from 'vue-router'

  /**
   * Route name map generated by vue-router file-based routing
   */
  export interface RouteNamedMap {
    '/': RouteRecordInfo<
      '/',
      '/',
      Record<never, never>,
      Record<never, never>,
      | never
    >
    '/about': RouteRecordInfo<
      '/about',
      '/about',
      Record<never, never>,
      Record<never, never>,
      | never
    >
    '/users/[id]': RouteRecordInfo<
      '/users/[id]',
      '/users/:id',
      { id: ParamValue<true> },
      { id: ParamValue<false> },
      | never
    >
  }
}

Volar Plugins

To get the best TypeScript experience in Single File Components, add the following Volar plugins to your tsconfig.json (or tsconfig.app.json):

tsconfig.json
jsonc
{
  "vueCompilerOptions": {
    "plugins": [
      "vue-router/volar/sfc-route-blocks",
      "vue-router/volar/sfc-typed-router",
    ],
  },
}
  • vue-router/volar/sfc-route-blocks — enables <route> blocks in SFCs for defining per-page route metadata
  • vue-router/volar/sfc-typed-router — makes useRoute() return a typed route based on the current page component, so route.params is correctly typed

Migrating an existing project

Move your page components to src/pages and rename them accordingly. Here is an example of migration. Given the following route configuration:

ts
import { createRouter, createWebHistory } from 'vue-router'
import { routes, handleHotUpdate } from 'vue-router/auto-routes'

export const router = createRouter({
  history: createWebHistory(),
  routes: [ 
    { 
      path: '/', 
      component: () => import('src/pages/Home.vue'), 
    }, 
    { 
      path: '/users/:id', 
      component: () => import('src/pages/User.vue'), 
    } 
    { 
      path: '/about', 
      component: () => import('src/pages/About.vue'), 
    }, 
  ] 
  routes, 
})

// This will update routes at runtime without reloading the page
if (import.meta.hot) { 
  handleHotUpdate(router) 
} 
ts
import { createApp } from 'vue'
import { router } from './router'
import App from './App.vue'

createApp(App).use(router).mount('#app')
  • Rename src/pages/Home.vue to src/pages/index.vue
  • Rename src/pages/User.vue to src/pages/users/[id].vue
  • Rename src/pages/About.vue to src/pages/about.vue

Check the file conventions guide for more information about the naming conventions.

From scratch

  • Create a src/pages folder and add an index.vue component to it. This will render your home page at /.
  • Import the routes from vue-router/auto-routes and pass them to the createRouter function.
ts
import { createApp } from 'vue'
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)
  .use(router)
  .mount('#app')
vue
<template>
  <h1>Home</h1>
</template>

Check the file conventions guide for more information about the naming conventions.

Manipulating the routes

You can pass the routes to any plugin that needs to add changes to them but note that these changes will not be reflected in types. Use build-time routes instead if you want to have types support. Here is an example with Vitesse starter:

ts
import { ViteSSG } from 'vite-ssg'
import { setupLayouts } from 'virtual:generated-layouts'
import App from './App.vue'
import type { UserModule } from './types'
import generatedRoutes from '~pages'
import { routes } from 'vue-router/auto-routes'

import '@unocss/reset/tailwind.css'
import './styles/main.css'
import 'uno.css'

const routes = setupLayouts(generatedRoutes) 

// https://github.com/antfu/vite-ssg
export const createApp = ViteSSG(
  App,
  {
    routes, 
    routes: setupLayouts(routes), 
    base: import.meta.env.BASE_URL,
  },
  ctx => {
    // install all modules under `modules/`
    Object.values(
      import.meta.glob<{ install: UserModule }>('./modules/*.ts', {
        eager: true,
      })
    ).forEach(i => i.install?.(ctx))
  }
)

ESLint

If you use ESlint, check the ESlint section.

Released under the MIT License.