Skip to content

Merge unplugin-vue-router#2603

Merged
posva merged 66 commits intomainfrom
merge/uvr
Jan 29, 2026
Merged

Merge unplugin-vue-router#2603
posva merged 66 commits intomainfrom
merge/uvr

Conversation

@posva
Copy link
Copy Markdown
Member

@posva posva commented Jan 15, 2026

This merges unplugin-vue-router into vue-router with minimal breaking changes. The goal is to release a v5 that is the closest possible to vue-router 4 to ease migration, then release a v6 that has other breaking changes like ESM only, removed deprecated features, improvements for types, etc

Vue Router 5 Migration Guide

Vue Router 5 merges unplugin-vue-router into the core package.


Migrating from unplugin-vue-router

If you're already using unplugin-vue-router, migration is straightforward—mostly import changes.

1. Update Dependencies

pnpm remove unplugin-vue-router
# once published
pnpm update vue-router@5
# for the moment
pnpm add https://pkg.pr.new/vue-router@2603

2. Update Imports

Vite plugin:

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

// After
import VueRouter from 'vue-router/vite'

Data loaders:

// Before
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
import { defineColadaLoader } from 'unplugin-vue-router/data-loaders/pinia-colada'
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders'

// After
import { defineBasicLoader, DataLoaderPlugin } from 'vue-router/experimental'
import { defineColadaLoader } from 'vue-router/experimental/pinia-colada'

Unplugin utilities (for custom integrations):

// Before
import {
  VueRouterAutoImports,
  EditableTreeNode,
  createTreeNodeValue,
  createRoutesContext,
  getFileBasedRouteName,
  getPascalCaseRouteName,
} from 'unplugin-vue-router'

// After
import {
  VueRouterAutoImports,
  EditableTreeNode,
  createTreeNodeValue,
  createRoutesContext,
  getFileBasedRouteName,
  getPascalCaseRouteName,
} from 'vue-router/unplugin'

Types:

// Before
import type { Options, EditableTreeNode } from 'unplugin-vue-router'

// After
import type { Options, EditableTreeNode } from 'vue-router/unplugin'

Volar plugins:

// Before (tsconfig.json)
{
  "compilerOptions": {
    // needed for the volar plugin
    "rootDir": "."
  },
  "vueCompilerOptions": {
    "plugins": [
      "unplugin-vue-router/volar/sfc-typed-router",
      "unplugin-vue-router/volar/sfc-route-blocks"
    ]
  }
}

// After
{
  "compilerOptions": {
    // needed for the volar plugin
    "rootDir": "."
  },
  "vueCompilerOptions": {
    "plugins": [
      "vue-router/volar/sfc-typed-router",
      "vue-router/volar/sfc-route-blocks"
    ]
  }
}

3. Update tsconfig.json

Remove the old client types reference:

// Before
{
  "include": ["./typed-router.d.ts", "unplugin-vue-router/client"]
}

// After
{
  "include": ["./typed-router.d.ts"]
}

Migration Checklist (unplugin-vue-router)

  • Remove unplugin-vue-router dependency
  • Update vue-router to v5
  • Change plugin import: unplugin-vue-router/vitevue-router/vite
  • Change data loader imports: unplugin-vue-router/data-loaders/*vue-router/experimental
  • Change utility imports: unplugin-vue-routervue-router/unplugin
  • Change Volar plugins: unplugin-vue-router/volar/*vue-router/volar/*
  • Remove unplugin-vue-router/client from tsconfig

Migrating from Vue Router 4 (without file-based routing)

1. Add Build Plugin

Vite:

// vite.config.ts
import VueRouter from 'vue-router/vite'

export default defineConfig({
  plugins: [
    VueRouter({
      // Recommended: auto-included by tsconfig
      dts: 'src/typed-router.d.ts',
    }),
    vue(),
  ],
})

Tip: Using dts: 'src/typed-router.d.ts' places the generated types inside src/, which is automatically included by most tsconfig.json setups. This will become the default in a future version.

Webpack:

// webpack.config.js
const VueRouter = require('vue-router/unplugin').default

module.exports = {
  plugins: [
    VueRouter.webpack({
      dts: 'src/typed-router.d.ts',
    }),
  ],
}

Rollup:

// rollup.config.js
import VueRouter from 'vue-router/unplugin'

export default {
  plugins: [
    VueRouter.rollup({
      dts: 'src/typed-router.d.ts',
    }),
  ],
}

esbuild:

import VueRouter from 'vue-router/unplugin'
import esbuild from 'esbuild'

esbuild.build({
  plugins: [
    VueRouter.esbuild({
      dts: 'src/typed-router.d.ts',
    }),
  ],
})

2. Update Routes Import

// Before
import Home from '@/views/Home.vue'
const routes = [{ path: '/', component: Home }]

// After
import { routes } from 'vue-router/auto-routes'

3. TypeScript Configuration

If using the recommended dts: 'src/typed-router.d.ts', no changes needed—it's auto-included.

Otherwise, add the generated types file to your config:

// tsconfig.json
{
  "include": ["./typed-router.d.ts"]
}

4. Move Page Components

Components must move to src/pages/ (configurable via routesFolder).

Old Location New Location Route
views/Home.vue pages/index.vue /
views/About.vue pages/about.vue /about
views/User.vue pages/users/[id].vue /users/:id
views/NotFound.vue pages/[...path].vue /:path(.*)

5. Update Route Names

Names are auto-generated from file paths:

File Path Generated Name
src/pages/index.vue '/'
src/pages/users/[id].vue '/users/[id]'
src/pages/users/[id]/posts.vue '/users/[id]/posts'

Update router.push() calls:

// Before
router.push({ name: 'user', params: { id: '123' } })

// After
router.push({ name: '/users/[id]', params: { id: '123' } })

To keep custom names, use definePage(), but it's recommended to let Vue Router manage names automatically for consistency.

<script setup lang="ts">
definePage({ name: 'user' })
</script>

6. File Naming Conventions

Dynamic routes:

Convention Becomes Example
[id] :id Required param
[[id]] :id? Optional param
[...path] :path(.*) Catch-all
[slugs]+ :slugs+ One or more
[[slugs]]+ :slugs+ Zero or more

Index routes with custom names:

Instead of index.vue, you can use parentheses to give the file a meaningful name without affecting the route:

File Route
pages/(home).vue /
pages/users/(list).vue /users

This helps keep your codebase organized with descriptive file names and also allows to group related pages together.

File Route
pages/(public)/(home).vue /
pages/(public)/about.vue /about
pages/(admin)/(dashboard).vue /admin

Migration Checklist (Vue Router 4)

  • Install vue-router@5
  • Add build plugin with dts: 'src/typed-router.d.ts'
  • Move page components to src/pages/
  • Change routes import to vue-router/auto-routes
  • Update router.push({ name: ... }) calls
  • Add definePage() where custom names needed

Hybrid Migration (Keep Manual Routes)

Mix file-based and manual routes:

import type { RouteRecordRaw } from 'vue-router'
import { routes as autoRoutes } from 'vue-router/auto-routes'

const manualRoutes: RouteRecordRaw[] = [
  { path: '/legacy', component: () => import('@/legacy/Page.vue') },
]

const router = createRouter({
  history: createWebHistory(),
  routes: [...autoRoutes, ...manualRoutes],
})

Troubleshooting

Types not recognized: Restart TS server, check typed-router.d.ts in tsconfig

Routes not generating: Verify routesFolder path, check file extensions

Route name errors: Use new generated names or add definePage({ name: 'old-name' })


New Exports Reference

Export Purpose
vue-router Main API (unchanged)
vue-router/vite Vite plugin
vue-router/auto-routes Generated routes
vue-router/unplugin Webpack/Rollup/esbuild + utilities
vue-router/experimental Data loaders
vue-router/experimental/pinia-colada Pinia Colada loader

New Features

Volar Plugins for Enhanced IDE Support

Vue Router 5 includes Volar plugins that provide automatic typing in your IDE. No more passing route names to useRoute()!

Setup in tsconfig.json:

{
  "compilerOptions": {
    // needed for the volar plugin
    "rootDir": ".",
  },
  "vueCompilerOptions": {
    "plugins": [
      "vue-router/volar/sfc-typed-router",
      "vue-router/volar/sfc-route-blocks",
    ],
  },
  "include": ["./typed-router.d.ts"],
}

What you get:

sfc-typed-router — Automatic useRoute() and $route typing based on the current file:

<!-- src/pages/users/[id].vue -->
<script setup lang="ts">
// Before: had to pass route name for typing
const route = useRoute('/users/[id]')

// After: automatically typed based on file location!
const route = useRoute()
route.params.id // ✅ typed as string
</script>

<template>
  <!-- $route is also automatically typed -->
  <p>User ID: {{ $route.params.id }}</p>
</template>

sfc-route-blocks — JSON/YAML validation and autocomplete for <route> blocks:

<route lang="json">
{
  "$schema": "https://router.vuejs.org/schemas/route.schema.json",
  "name": "user-profile",
  "meta": { "requiresAuth": true }
}
</route>

Route Customization

Using definePage() macro

<script setup lang="ts">
definePage({
  name: 'custom-name',
  path: '/custom-path',
  meta: { requiresAuth: true },
  alias: ['/alternate'],
})
</script>

Using <route> block

<route lang="json5">
{
  name: 'custom-name',
  meta: { requiresAuth: true },
}
</route>

Using plugin config

VueRouter({
  extendRoute(route) {
    if (route.path === '/admin') {
      route.addToMeta({ requiresAdmin: true })
    }
  },
})

Plugin Configuration

VueRouter({
  routesFolder: 'src/pages',
  extensions: ['.vue'],
  exclude: ['**/components/**'],
  importMode: 'async',
  dts: 'src/typed-router.d.ts', // Recommended
  routeBlockLang: 'json5',
})

@netlify
Copy link
Copy Markdown

netlify bot commented Jan 15, 2026

Deploy Preview for vue-router ready!

Name Link
🔨 Latest commit 45da91e
🔍 Latest deploy log https://app.netlify.com/projects/vue-router/deploys/697b72cdaeeb1500080f351f
😎 Deploy Preview https://deploy-preview-2603--vue-router.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 88 (🔴 down 1 from production)
Accessibility: 100 (no change from production)
Best Practices: 92 (🟢 up 9 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 15, 2026

Important

Review skipped

Too many files!

This PR contains 286 files, which is 186 over the limit of 100.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Jan 15, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vue-router@2603

commit: 45da91e

@codecov
Copy link
Copy Markdown

codecov bot commented Jan 15, 2026

Codecov Report

❌ Patch coverage is 90.15748% with 300 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.26%. Comparing base (bdfa2f4) to head (45da91e).
⚠️ Report is 69 commits behind head on main.

Files with missing lines Patch % Lines
...uter/src/experimental/data-loaders/auto-exports.ts 0.00% 62 Missing and 1 partial ⚠️
packages/router/src/tests/vitest-mock-warn.ts 43.80% 59 Missing ⚠️
...ackages/router/src/unplugin/codegen/generateDTS.ts 0.00% 29 Missing and 1 partial ⚠️
.../src/experimental/data-loaders/navigation-guard.ts 86.31% 26 Missing ⚠️
packages/router/src/tests/data-loaders/tester.ts 98.27% 25 Missing ⚠️
...rc/experimental/data-loaders/defineColadaLoader.ts 93.25% 22 Missing ⚠️
...outer/src/unplugin/codegen/generateRouteRecords.ts 85.38% 19 Missing ⚠️
packages/router/src/experimental/runtime.ts 11.76% 15 Missing ⚠️
...uter/src/experimental/data-loaders/defineLoader.ts 94.39% 13 Missing ⚠️
...ages/router/src/experimental/data-loaders/utils.ts 81.42% 13 Missing ⚠️
... and 4 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2603      +/-   ##
==========================================
- Coverage   91.27%   85.26%   -6.01%     
==========================================
  Files          46       84      +38     
  Lines        4181     9774    +5593     
  Branches     1114     2219    +1105     
==========================================
+ Hits         3816     8334    +4518     
- Misses        358     1428    +1070     
- Partials        7       12       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@posva posva merged commit 7ba2832 into main Jan 29, 2026
8 of 9 checks passed
@posva posva deleted the merge/uvr branch January 29, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants