From b1fb9d22b7efee5e95f5697aa4a164cb91a69623 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 5 Apr 2022 14:01:17 +0100 Subject: [PATCH 1/4] fix(nuxt3): sync route object to currently resolved page --- packages/nuxt3/src/pages/runtime/router.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/nuxt3/src/pages/runtime/router.ts b/packages/nuxt3/src/pages/runtime/router.ts index a55bb7586f5..33737fb0f61 100644 --- a/packages/nuxt3/src/pages/runtime/router.ts +++ b/packages/nuxt3/src/pages/runtime/router.ts @@ -3,7 +3,8 @@ import { createRouter, createWebHistory, createMemoryHistory, - NavigationGuard + NavigationGuard, + RouteLocation } from 'vue-router' import { createError } from 'h3' import NuxtPage from './page' @@ -52,10 +53,23 @@ export default defineNuxtPlugin((nuxtApp) => { get: () => previousRoute.value }) + // Allows suspending the route object until page navigation completes + const path = process.server ? nuxtApp.ssrContext.req.url : window.location.pathname + const currentRoute = shallowRef(router.resolve(path) as RouteLocation) + router.afterEach((to, from) => { + // We won't trigger suspense if the component is reused between routes + // so we need to update the route manually + if (to.matched[0]?.components?.default === from.matched[0]?.components?.default) { + currentRoute.value = router.currentRoute.value + } + }) + nuxtApp.hook('page:finish', () => { + currentRoute.value = router.currentRoute.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]) + for (const key in currentRoute.value) { + route[key] = computed(() => currentRoute.value[key]) } nuxtApp._route = reactive(route) From 2ed6f4966da5a15ab18a39c265d99cfc9154aff8 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 5 Apr 2022 14:17:51 +0100 Subject: [PATCH 2/4] fix: resolve full path (with query + hash) --- packages/nuxt3/src/pages/runtime/router.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nuxt3/src/pages/runtime/router.ts b/packages/nuxt3/src/pages/runtime/router.ts index 33737fb0f61..2f6dd039139 100644 --- a/packages/nuxt3/src/pages/runtime/router.ts +++ b/packages/nuxt3/src/pages/runtime/router.ts @@ -7,6 +7,7 @@ import { RouteLocation } from 'vue-router' import { createError } from 'h3' +import { withoutBase } from 'ufo' import NuxtPage from './page' import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, throwError, clearError } from '#app' // @ts-ignore @@ -54,7 +55,7 @@ export default defineNuxtPlugin((nuxtApp) => { }) // Allows suspending the route object until page navigation completes - const path = process.server ? nuxtApp.ssrContext.req.url : window.location.pathname + const path = process.server ? nuxtApp.ssrContext.req.url : withoutBase(window.location.href, window.location.origin) const currentRoute = shallowRef(router.resolve(path) as RouteLocation) router.afterEach((to, from) => { // We won't trigger suspense if the component is reused between routes From 27adc3a4a1471f0ba710f45fd1c963c209dfc17c Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 5 Apr 2022 14:26:06 +0100 Subject: [PATCH 3/4] refactor: `syncCurrentRoute` --- packages/nuxt3/src/pages/runtime/router.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/nuxt3/src/pages/runtime/router.ts b/packages/nuxt3/src/pages/runtime/router.ts index 2f6dd039139..a8b391a92a1 100644 --- a/packages/nuxt3/src/pages/runtime/router.ts +++ b/packages/nuxt3/src/pages/runtime/router.ts @@ -57,16 +57,15 @@ export default defineNuxtPlugin((nuxtApp) => { // Allows suspending the route object until page navigation completes const path = process.server ? nuxtApp.ssrContext.req.url : withoutBase(window.location.href, window.location.origin) const currentRoute = shallowRef(router.resolve(path) as RouteLocation) + const syncCurrentRoute = () => { currentRoute.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 // so we need to update the route manually if (to.matched[0]?.components?.default === from.matched[0]?.components?.default) { - currentRoute.value = router.currentRoute.value + syncCurrentRoute() } }) - nuxtApp.hook('page:finish', () => { - currentRoute.value = router.currentRoute.value - }) // https://github.com/vuejs/vue-router-next/blob/master/src/router.ts#L1192-L1200 const route = {} for (const key in currentRoute.value) { From 297c87e64113280fec32b4472273d200c0471cb0 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 5 Apr 2022 15:36:21 +0100 Subject: [PATCH 4/4] fix: use `vue-router` implementation --- packages/nuxt3/src/pages/runtime/router.ts | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/nuxt3/src/pages/runtime/router.ts b/packages/nuxt3/src/pages/runtime/router.ts index a8b391a92a1..650ae07fbfb 100644 --- a/packages/nuxt3/src/pages/runtime/router.ts +++ b/packages/nuxt3/src/pages/runtime/router.ts @@ -27,6 +27,27 @@ declare module 'vue' { } } +// https://github.dev/vuejs/router/blob/main/src/history/html5.ts#L33-L56 +function createCurrentLocation ( + base: string, + location: Location +): string { + const { pathname, search, hash } = location + // allows hash bases like #, /#, #/, #!, #!/, /#!/, or even /folder#end + const hashPos = base.indexOf('#') + if (hashPos > -1) { + const slicePos = hash.includes(base.slice(hashPos)) + ? base.slice(hashPos).length + : 1 + let pathFromHash = hash.slice(slicePos) + // prepend the starting slash to hash so the url starts with /# + if (pathFromHash[0] !== '/') { pathFromHash = '/' + pathFromHash } + return withoutBase(pathFromHash, '') + } + const path = withoutBase(pathname, base) + return path + search + hash +} + export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.component('NuxtPage', NuxtPage) // TODO: remove before release - present for backwards compatibility & intentionally undocumented @@ -55,7 +76,7 @@ export default defineNuxtPlugin((nuxtApp) => { }) // Allows suspending the route object until page navigation completes - const path = process.server ? nuxtApp.ssrContext.req.url : withoutBase(window.location.href, window.location.origin) + const path = process.server ? nuxtApp.ssrContext.req.url : createCurrentLocation(baseURL, window.location) const currentRoute = shallowRef(router.resolve(path) as RouteLocation) const syncCurrentRoute = () => { currentRoute.value = router.currentRoute.value } nuxtApp.hook('page:finish', syncCurrentRoute)