fix(nuxt): separate routes for different suspense forks (#6275)

This commit is contained in:
Daniel Roe 2022-08-02 10:58:03 +01:00 committed by GitHub
parent b12fe7eb7c
commit c72093b1f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 28 deletions

View File

@ -6,14 +6,17 @@
</template>
<script setup>
import { defineAsyncComponent, onErrorCaptured } from 'vue'
import { callWithNuxt, isNuxtError, showError, useError, useNuxtApp } from '#app'
import { defineAsyncComponent, onErrorCaptured, provide } from 'vue'
import { callWithNuxt, isNuxtError, showError, useError, useRoute, useNuxtApp } from '#app'
const ErrorComponent = defineAsyncComponent(() => import('#build/error-component.mjs'))
const nuxtApp = useNuxtApp()
const onResolve = () => nuxtApp.callHook('app:suspense:resolve')
// Inject default route (outside of pages) as active route
provide('_route', useRoute())
// vue:setup hook
const results = nuxtApp.hooks.callHookWith(hooks => hooks.map(hook => hook()), 'vue:setup')
if (process.dev && results && results.some(i => i && 'then' in i)) {

View File

@ -1,3 +1,4 @@
import { getCurrentInstance, inject } from 'vue'
import type { Router, RouteLocationNormalizedLoaded, NavigationGuard, RouteLocationNormalized, RouteLocationRaw, NavigationFailure } from 'vue-router'
import { sendRedirect } from 'h3'
import { joinURL } from 'ufo'
@ -8,11 +9,15 @@ export const useRouter = () => {
}
export const useRoute = () => {
return useNuxtApp()._route as RouteLocationNormalizedLoaded
if (getCurrentInstance()) {
return inject<RouteLocationNormalizedLoaded>('_route', useNuxtApp()._route)
}
return useNuxtApp()._route
}
/** @deprecated Use `useRoute` instead. */
export const useActiveRoute = () => {
return useNuxtApp()._activeRoute as RouteLocationNormalizedLoaded
return useNuxtApp()._route as RouteLocationNormalizedLoaded
}
export interface RouteMiddleware {

View File

@ -30,17 +30,28 @@ export default defineComponent({
return () => {
return h(RouterView, { name: props.name, route: props.route, ...attrs }, {
default: (routeProps: RouterViewSlotProps) => routeProps.Component &&
_wrapIf(Transition, routeProps.route.meta.pageTransition ?? defaultPageTransition,
wrapInKeepAlive(routeProps.route.meta.keepalive,
isNested && nuxtApp.isHydrating
// Include route children in parent suspense
? h(routeProps.Component, { key: generateRouteKey(props.pageKey, routeProps) } as {})
: h(Suspense, {
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
onResolve: () => nuxtApp.callHook('page:finish', routeProps.Component)
}, { default: () => h(routeProps.Component, { key: generateRouteKey(props.pageKey, routeProps) } as {}) })
)).default()
default: (routeProps: RouterViewSlotProps) => {
if (!routeProps.Component) { return }
const Component = defineComponent({
setup () {
provide('_route', routeProps.route)
return () => h(routeProps.Component, {
key: generateRouteKey(props.pageKey, routeProps)
} as {})
}
})
return _wrapIf(Transition, routeProps.route.meta.pageTransition ?? defaultPageTransition,
wrapInKeepAlive(routeProps.route.meta.keepalive, isNested && nuxtApp.isHydrating
// Include route children in parent suspense
? h(Component)
: h(Suspense, {
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
onResolve: () => nuxtApp.callHook('page:finish', routeProps.Component)
}, { default: () => h(Component) })
)).default()
}
})
}
}

View File

@ -76,15 +76,9 @@ export default defineNuxtPlugin(async (nuxtApp) => {
get: () => previousRoute.value
})
// https://github.com/vuejs/vue-router-next/blob/master/src/router.ts#L1192-L1200
const route = {}
for (const key in router.currentRoute.value) {
route[key] = computed(() => router.currentRoute.value[key])
}
// Allows suspending the route object until page navigation completes
const _activeRoute = shallowRef(router.resolve(initialURL) as RouteLocation)
const syncCurrentRoute = () => { _activeRoute.value = router.currentRoute.value }
const _route = shallowRef(router.resolve(initialURL) as RouteLocation)
const syncCurrentRoute = () => { _route.value = router.currentRoute.value }
nuxtApp.hook('page:finish', syncCurrentRoute)
router.afterEach((to, from) => {
// We won't trigger suspense if the component is reused between routes
@ -93,14 +87,14 @@ export default defineNuxtPlugin(async (nuxtApp) => {
syncCurrentRoute()
}
})
// https://github.com/vuejs/vue-router-next/blob/master/src/router.ts#L1192-L1200
const activeRoute = {}
for (const key in _activeRoute.value) {
activeRoute[key] = computed(() => _activeRoute.value[key])
// https://github.com/vuejs/router/blob/main/packages/router/src/router.ts#L1225-L1233
const route = {}
for (const key in _route.value) {
route[key] = computed(() => _route.value[key])
}
nuxtApp._route = reactive(route)
nuxtApp._activeRoute = reactive(activeRoute)
nuxtApp._middleware = nuxtApp._middleware || {
global: [],