Skip to content

Introduction

Installation

Install using your favorite package manager:

bash
npm install -D unplugin-vue-router

Add the plugin to your bundler:

ts
import VueRouter from 'unplugin-vue-router/vite'

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

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

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

Setup

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 unplugin-vue-router/client to types and "moduleResolution": "Bundler". This is what it should look like:

json
{
  "include": [
    // other files...
    "./typed-router.d.ts"
  ],
  "compilerOptions": {
    // ...
    "moduleResolution": "Bundler",
    "types": [
      // other types...
      "unplugin-vue-router/client"
    ]
    // other options...
  }
}
ts
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-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 'unplugin-vue-router/types'

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

Instead of importing from vue-router, you should import from vue-router/auto.

TIP

You can exclude vue-router from VSCode import suggestions by adding this setting to your .vscode/settings.json:

json
{
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.preferences.autoImportFileExcludePatterns": ["vue-router$"]
}

This will ensure VSCode only suggests vue-router/auto for imports. Alternatively, you can also configure auto imports.

The reason we need to import from vue-router/auto rather than vue-router is because we override all the types with typed version. It is not possible to override the types from vue-router directly as the typed ones are all generic.

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 { createRouter, createWebHistory } from 'vue-router/auto'

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'), 
    }, 
  ] 
})
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-based routing 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 /.
  • Add Vue Router using vue-router/auto instead of vue-router. These types are augmented to be fully typed.
ts
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router/auto'
import App from './App.vue'

const router = createRouter({
  history: createWebHistory(),
  // the routes property is handled by the plugin
})

createApp(App)
  .use(router)
  .mount('#app')
vue
<template>
  <h1>Home</h1>
</template>

Check the file-based routing guide for more information about the naming conventions.

Passing the routes manually

Alternatively, you can also import the routes array and create the router manually or pass it to some plugin. 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))
  }
)

Auto Imports

If you are using unplugin-auto-import, make sure to remove the vue-router preset and use the one exported by unplugin-vue-router:

ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import { VueRouterAutoImports } from 'unplugin-vue-router'

export default defineConfig({
  plugins: [
    // other plugins
    AutoImport({
      imports: [
        'vue-router', 
        VueRouterAutoImports, 
      ],
    }),
  ],
})

Note that the vue-router preset might export less things than the one exported by unplugin-vue-router so you might need to add any other imports you were relying on manually:

ts
AutoImport({
  imports: [
    VueRouterAutoImports,
    { 
        // add any other imports you were relying on
        'vue-router/auto': ['useLink'] 
    }, 
  ],
}),

If you use ESlint, check the ESlint section. If you use TypeScript or have a jsconfig.json file, check the TypeScript section.

Released under the MIT License.