perf(nuxt): reduce router resolutions (#26519)

This commit is contained in:
Daniel Roe 2024-04-03 10:56:27 +01:00 committed by GitHub
parent d38d7e59b2
commit be49918139
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -9,7 +9,7 @@ import {
createWebHistory createWebHistory
} from '#vue-router' } from '#vue-router'
import { createError } from 'h3' import { createError } from 'h3'
import { isEqual, withoutBase } from 'ufo' import { isEqual, isSamePath, withoutBase } from 'ufo'
import type { PageMeta } from '../composables' import type { PageMeta } from '../composables'
@ -70,9 +70,6 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
const routes = routerOptions.routes?.(_routes) ?? _routes const routes = routerOptions.routes?.(_routes) ?? _routes
let startPosition: Parameters<RouterScrollBehavior>[2] | null let startPosition: Parameters<RouterScrollBehavior>[2] | null
const initialURL = import.meta.server
? nuxtApp.ssrContext!.url
: createCurrentLocation(routerBase, window.location, nuxtApp.payload.path)
const router = createRouter({ const router = createRouter({
...routerOptions, ...routerOptions,
@ -111,8 +108,12 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
get: () => previousRoute.value get: () => previousRoute.value
}) })
const initialURL = import.meta.server
? nuxtApp.ssrContext!.url
: createCurrentLocation(routerBase, window.location, nuxtApp.payload.path)
// Allows suspending the route object until page navigation completes // Allows suspending the route object until page navigation completes
const _route = shallowRef(router.resolve(initialURL) as RouteLocation) const _route = shallowRef(router.currentRoute.value)
const syncCurrentRoute = () => { _route.value = router.currentRoute.value } const syncCurrentRoute = () => { _route.value = router.currentRoute.value }
nuxtApp.hook('page:finish', syncCurrentRoute) nuxtApp.hook('page:finish', syncCurrentRoute)
router.afterEach((to, from) => { router.afterEach((to, from) => {
@ -138,19 +139,21 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
named: {} named: {}
} }
const error = useError()
try { try {
if (import.meta.server) { if (import.meta.server) {
await router.push(initialURL) await router.push(initialURL)
} }
await router.isReady() await router.isReady()
} catch (error: any) { } catch (error: any) {
// We'll catch 404s here // We'll catch 404s here
await nuxtApp.runWithContext(() => showError(error)) await nuxtApp.runWithContext(() => showError(error))
} }
const resolvedInitialRoute = import.meta.client && initialURL !== router.currentRoute.value.fullPath
? router.resolve(initialURL)
: router.currentRoute.value
syncCurrentRoute()
if (import.meta.server && nuxtApp.ssrContext?.islandContext) { if (import.meta.server && nuxtApp.ssrContext?.islandContext) {
// We're in an island context, and don't need to handle middleware or redirections // We're in an island context, and don't need to handle middleware or redirections
return { provide: { router } } return { provide: { router } }
@ -225,6 +228,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
await nuxtApp.callHook('page:loading:end') await nuxtApp.callHook('page:loading:end')
}) })
const error = useError()
router.afterEach(async (to, _from, failure) => { router.afterEach(async (to, _from, failure) => {
delete nuxtApp._processingMiddleware delete nuxtApp._processingMiddleware
@ -247,18 +251,19 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
path: to.fullPath path: to.fullPath
} }
}))) })))
} else if (import.meta.server && to.redirectedFrom && to.fullPath !== initialURL) { } else if (import.meta.server && to.fullPath !== initialURL && (to.redirectedFrom || !isSamePath(to.fullPath, initialURL))) {
await nuxtApp.runWithContext(() => navigateTo(to.fullPath || '/')) await nuxtApp.runWithContext(() => navigateTo(to.fullPath || '/'))
} }
}) })
nuxtApp.hooks.hookOnce('app:created', async () => { nuxtApp.hooks.hookOnce('app:created', async () => {
try { try {
const to = router.resolve(initialURL)
// #4920, #4982 // #4920, #4982
if ('name' in to) { to.name = undefined } if ('name' in resolvedInitialRoute) {
resolvedInitialRoute.name = undefined
}
await router.replace({ await router.replace({
...to, ...resolvedInitialRoute,
force: true force: true
}) })
// reset scroll behavior to initial value // reset scroll behavior to initial value