Skip to content
This repository was archived by the owner on Apr 6, 2023. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions packages/nuxt3/src/pages/runtime/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import {
createRouter,
createWebHistory,
createMemoryHistory,
NavigationGuard
NavigationGuard,
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
Expand All @@ -25,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
Expand Down Expand Up @@ -52,10 +75,22 @@ export default defineNuxtPlugin((nuxtApp) => {
get: () => previousRoute.value
})

// Allows suspending the route object until page navigation completes
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)
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) {
syncCurrentRoute()
}
})
// 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)
Expand Down