fix(nuxt): respect router.options when hmring routes (#30455)

This commit is contained in:
Daniel Roe 2025-01-04 22:35:36 +00:00
parent 6a6bae73ea
commit d837cee9d1
No known key found for this signature in database
GPG Key ID: CBC814C393D93268
4 changed files with 27 additions and 9 deletions

View File

@ -5,3 +5,13 @@ declare module '#build/router.options' {
const _default: RouterOptions
export default _default
}
declare module '#build/routes' {
import type { RouterOptions } from '@nuxt/schema'
import type { Router, RouterOptions as VueRouterOptions } from 'vue-router'
export const handleHotUpdate: (_router: Router, _generateRoutes: RouterOptions['routes']) => void
const _default: VueRouterOptions['routes']
export default _default
}

View File

@ -621,22 +621,32 @@ const ROUTES_HMR_CODE = /* js */`
if (import.meta.hot) {
import.meta.hot.accept((mod) => {
const router = import.meta.hot.data.router
if (!router) {
const generateRoutes = import.meta.hot.data.generateRoutes
if (!router || !generateRoutes) {
import.meta.hot.invalidate('[nuxt] Cannot replace routes because there is no active router. Reloading.')
return
}
router.clearRoutes()
for (const route of mod.default || mod) {
router.addRoute(route)
const routes = generateRoutes(mod.default || mod)
function addRoutes (routes) {
for (const route of routes) {
router.addRoute(route)
}
router.replace('')
}
if (routes && 'then' in routes) {
routes.then(addRoutes)
} else {
addRoutes(routes)
}
router.replace('')
})
}
export function handleHotUpdate(_router) {
export function handleHotUpdate(_router, _generateRoutes) {
if (import.meta.hot) {
import.meta.hot.data ||= {}
import.meta.hot.data.router = _router
import.meta.hot.data.generateRoutes = _generateRoutes
}
}
`

View File

@ -5,7 +5,6 @@ import defu from 'defu'
import { defineNuxtPlugin, useRuntimeConfig } from '#app/nuxt'
import { prerenderRoutes } from '#app/composables/ssr'
// @ts-expect-error virtual file
import _routes from '#build/routes'
import routerOptions, { hashMode } from '#build/router.options'
// @ts-expect-error virtual file
@ -39,7 +38,7 @@ function shouldPrerender (path: string) {
return !_routeRulesMatcher || defu({} as Record<string, any>, ..._routeRulesMatcher.matchAll(path).reverse()).prerender
}
function processRoutes (routes: RouteRecordRaw[], currentPath = '/', routesToPrerender = new Set<string>()) {
function processRoutes (routes: readonly RouteRecordRaw[], currentPath = '/', routesToPrerender = new Set<string>()) {
for (const route of routes) {
// Add root of optional dynamic paths and catchalls
if (OPTIONAL_PARAM_RE.test(route.path) && !route.children?.length && shouldPrerender(currentPath)) {

View File

@ -17,7 +17,6 @@ import { navigateTo } from '#app/composables/router'
// @ts-expect-error virtual file
import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs'
// @ts-expect-error virtual file
import _routes, { handleHotUpdate } from '#build/routes'
import routerOptions, { hashMode } from '#build/router.options'
// @ts-expect-error virtual file
@ -88,7 +87,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
routes,
})
handleHotUpdate(router)
handleHotUpdate(router, routerOptions.routes ? routerOptions.routes : routes => routes)
if (import.meta.client && 'scrollRestoration' in window.history) {
window.history.scrollRestoration = 'auto'