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 "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 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> }>,
  }
}

Then, if you have an env.d.ts file like the one created by npm vue create <my-project>, add the unplugin-vue-router/client types to it:

ts
/// <reference types="vite/client" />
/// <reference types="unplugin-vue-router/client" />

If you don't have an env.d.ts file, you can create one and add the unplugin-vue-router types to it or you can add them to the types property in your tsconfig.json:

json
{
  "compilerOptions": {
    // ...
    "types": [
      "unplugin-vue-router/client"
    ]
  }
}

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.