Skip to content

Migration ​

If you are migrating an older setup, use Vue Router 5 file-based routing as the route source and let this plugin handle layouts only.

1. Remove legacy page-route plugin dependencies and types ​

diff
- import Pages from 'vite-plugin-pages'
- /// <reference types="vite-plugin-pages/client" />

2. Add Vue Router 5's Vite plugin before Vue ​

vite.config.js
diff
 import Vue from '@vitejs/plugin-vue'
+import VueRouter from 'vue-router/vite'
 import Layouts from 'vite-plugin-vue-layouts-next'

 export default defineConfig({
-  plugins: [Vue(), Pages(), Layouts()],
+  plugins: [VueRouter(), Vue(), Layouts()],
 })

3. Replace generated page-route imports with Vue Router 5 auto routes ​

diff
 import { setupLayouts } from 'virtual:generated-layouts'
-import generatedRoutes from 'virtual:generated-pages'
-import generatedRoutes from '~pages'
+import { routes } from 'vue-router/auto-routes'

-const routes = setupLayouts(generatedRoutes)
+const layoutRoutes = setupLayouts(routes)

4. Drop pagesDirs ​

Remove pagesDirs from Layouts() options. Vue Router 5 owns page discovery and route HMR; this plugin only watches and resolves layouts.

Layout name normalization ​

v3 uses Nuxt-compatible layout names. Nested layout names no longer use slash-separated paths.

diff
 definePage({
   meta: {
-    layout: 'sub/layoutsub',
+    layout: 'sub-layoutsub',
   },
 })

See Layout names for the full normalization table.

Redirects and other route options ​

vite-plugin-pages let a <route> block set any route record field. With Vue Router 5 file-based routing, use definePage() instead - the same way Nuxt's definePageMeta() works. It accepts the route record fields a page can own, such as name, path, alias, meta, props, redirect and beforeEnter; component and children come from the file tree and cannot be overridden. setupLayouts keeps these fields on the route record, so they work with layouts too.

For example, a page at src/pages/settings/legacy.vue that forwards to the new settings page:

diff
-<route>
-{
-  "name": "settings-legacy",
-  "meta": { "title": "Settings" },
-  "redirect": { "name": "/settings/profile" }
-}
-</route>
+<script setup lang="ts">
+definePage({
+  name: 'settings-legacy',
+  meta: { title: 'Settings' },
+  redirect: { name: '/settings/profile' },
+})
+</script>

Route names are generated from the file path by default (src/pages/settings/profile.vue becomes /settings/profile), so a redirect target must use that name unless the target page overrides it with definePage({ name: '...' }).

Released under the MIT License.