fix(nuxt): stop tracking suspense when error hydrating page (#25389)

This commit is contained in:
Daniel Roe 2024-01-23 12:31:39 +00:00 committed by GitHub
parent 48ce560901
commit 7e375b5ed8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 6 deletions

View File

@ -5,7 +5,7 @@ import type { RouteLocationNormalizedLoaded } from 'vue-router'
// eslint-disable-next-line import/no-restricted-paths // eslint-disable-next-line import/no-restricted-paths
import type { PageMeta } from '../../pages/runtime/composables' import type { PageMeta } from '../../pages/runtime/composables'
import { useRoute } from '../composables/router' import { useRoute, useRouter } from '../composables/router'
import { useNuxtApp } from '../nuxt' import { useNuxtApp } from '../nuxt'
import { _wrapIf } from './utils' import { _wrapIf } from './utils'
import { LayoutMetaSymbol, PageRouteSymbol } from './injections' import { LayoutMetaSymbol, PageRouteSymbol } from './injections'
@ -71,6 +71,10 @@ export default defineComponent({
context.expose({ layoutRef }) context.expose({ layoutRef })
const done = nuxtApp.deferHydration() const done = nuxtApp.deferHydration()
if (import.meta.client && nuxtApp.isHydrating) {
const removeErrorHook = nuxtApp.hooks.hookOnce('app:error', done)
useRouter().beforeEach(removeErrorHook)
}
if (import.meta.dev) { if (import.meta.dev) {
nuxtApp._isNuxtLayoutUsed = true nuxtApp._isNuxtLayoutUsed = true
@ -97,7 +101,7 @@ export default defineComponent({
} }
} }
}) as unknown as DefineComponent<{ }) as unknown as DefineComponent<{
name?: (unknown extends PageMeta['layout'] ? MaybeRef<string | false> : PageMeta['layout']) | undefined; name?: (unknown extends PageMeta['layout'] ? MaybeRef<string | false> : PageMeta['layout']) | undefined
}> }>
const LayoutProvider = defineComponent({ const LayoutProvider = defineComponent({

View File

@ -20,7 +20,7 @@
import { defineAsyncComponent, onErrorCaptured, onServerPrefetch, provide } from 'vue' import { defineAsyncComponent, onErrorCaptured, onServerPrefetch, provide } from 'vue'
import { useNuxtApp } from '../nuxt' import { useNuxtApp } from '../nuxt'
import { isNuxtError, showError, useError } from '../composables/error' import { isNuxtError, showError, useError } from '../composables/error'
import { useRoute } from '../composables/router' import { useRoute, useRouter } from '../composables/router'
import { PageRouteSymbol } from '../components/injections' import { PageRouteSymbol } from '../components/injections'
import AppComponent from '#build/app-component.mjs' import AppComponent from '#build/app-component.mjs'
import ErrorComponent from '#build/error-component.mjs' import ErrorComponent from '#build/error-component.mjs'
@ -31,6 +31,10 @@ const IslandRenderer = import.meta.server
const nuxtApp = useNuxtApp() const nuxtApp = useNuxtApp()
const onResolve = nuxtApp.deferHydration() const onResolve = nuxtApp.deferHydration()
if (import.meta.client && nuxtApp.isHydrating) {
const removeErrorHook = nuxtApp.hooks.hookOnce('app:error', onResolve)
useRouter().beforeEach(removeErrorHook)
}
const url = import.meta.server ? nuxtApp.ssrContext.url : window.location.pathname const url = import.meta.server ? nuxtApp.ssrContext.url : window.location.pathname
const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && defineAsyncComponent(() => import('#build/test-component-wrapper.mjs') const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && defineAsyncComponent(() => import('#build/test-component-wrapper.mjs')

View File

@ -9,6 +9,7 @@ import type { RouterViewSlotProps } from './utils'
import { generateRouteKey, wrapInKeepAlive } from './utils' import { generateRouteKey, wrapInKeepAlive } from './utils'
import { RouteProvider } from '#app/components/route-provider' import { RouteProvider } from '#app/components/route-provider'
import { useNuxtApp } from '#app/nuxt' import { useNuxtApp } from '#app/nuxt'
import { useRouter } from '#app/composables/router'
import { _wrapIf } from '#app/components/utils' import { _wrapIf } from '#app/components/utils'
import { LayoutMetaSymbol, PageRouteSymbol } from '#app/components/injections' import { LayoutMetaSymbol, PageRouteSymbol } from '#app/components/injections'
// @ts-expect-error virtual file // @ts-expect-error virtual file
@ -49,6 +50,10 @@ export default defineComponent({
let vnode: VNode let vnode: VNode
const done = nuxtApp.deferHydration() const done = nuxtApp.deferHydration()
if (import.meta.client && nuxtApp.isHydrating) {
const removeErrorHook = nuxtApp.hooks.hookOnce('app:error', done)
useRouter().beforeEach(removeErrorHook)
}
if (props.pageKey) { if (props.pageKey) {
watch(() => props.pageKey, (next, prev) => { watch(() => props.pageKey, (next, prev) => {
@ -151,12 +156,12 @@ function haveParentRoutesRendered (fork: RouteLocationNormalizedLoaded | null, n
return newRoute.matched.slice(0, index) return newRoute.matched.slice(0, index)
.some( .some(
(c, i) => c.components?.default !== fork.matched[i]?.components?.default) || (c, i) => c.components?.default !== fork.matched[i]?.components?.default) ||
(Component && generateRouteKey({ route: newRoute, Component }) !== generateRouteKey({ route: fork, Component })) (Component && generateRouteKey({ route: newRoute, Component }) !== generateRouteKey({ route: fork, Component }))
} }
function hasChildrenRoutes (fork: RouteLocationNormalizedLoaded | null, newRoute: RouteLocationNormalizedLoaded, Component?: VNode) { function hasChildrenRoutes (fork: RouteLocationNormalizedLoaded | null, newRoute: RouteLocationNormalizedLoaded, Component?: VNode) {
if (!fork) { return false } if (!fork) { return false }
const index = newRoute.matched.findIndex(m => m.components?.default === Component?.type) const index = newRoute.matched.findIndex(m => m.components?.default === Component?.type)
return index < newRoute.matched.length -1 return index < newRoute.matched.length - 1
} }