mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
feat(router): add proper server side redirection to navigateTo (#3684)
Co-authored-by: pooya parsa <pyapar@gmail.com>
This commit is contained in:
parent
93da7978fb
commit
99705f77c0
@ -4,6 +4,7 @@ import type { MetaInfo } from 'vue-meta'
|
|||||||
import type VueRouter from 'vue-router'
|
import type VueRouter from 'vue-router'
|
||||||
import type { Location, Route } from 'vue-router'
|
import type { Location, Route } from 'vue-router'
|
||||||
import type { RuntimeConfig } from '@nuxt/schema'
|
import type { RuntimeConfig } from '@nuxt/schema'
|
||||||
|
import { sendRedirect } from 'h3'
|
||||||
import defu from 'defu'
|
import defu from 'defu'
|
||||||
import { useNuxtApp } from './app'
|
import { useNuxtApp } from './app'
|
||||||
|
|
||||||
@ -172,12 +173,23 @@ const isProcessingMiddleware = () => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
export const navigateTo = (to: Route) => {
|
export interface NavigateToOptions {
|
||||||
|
replace?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const navigateTo = (to: Route, options: NavigateToOptions = {}) => {
|
||||||
if (isProcessingMiddleware()) {
|
if (isProcessingMiddleware()) {
|
||||||
return to
|
return to
|
||||||
}
|
}
|
||||||
const router: VueRouter = process.server ? useRouter() : (window as any).$nuxt.$router
|
const router = useRouter()
|
||||||
return router.push(to)
|
if (process.server && useNuxtApp().ssrContext) {
|
||||||
|
// Server-side redirection using h3 res from ssrContext
|
||||||
|
const res = useNuxtApp().ssrContext?.res
|
||||||
|
const redirectLocation = router.resolve(to).route.fullPath
|
||||||
|
return sendRedirect(res, redirectLocation)
|
||||||
|
}
|
||||||
|
// Client-side redirection using vue-router
|
||||||
|
return options.replace ? router.replace(to) : router.push(to)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This will abort navigation within a Nuxt route middleware handler. */
|
/** This will abort navigation within a Nuxt route middleware handler. */
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import type { Router, RouteLocationNormalizedLoaded, NavigationGuard, RouteLocationNormalized, RouteLocationRaw } from 'vue-router'
|
import type { Router, RouteLocationNormalizedLoaded, NavigationGuard, RouteLocationNormalized, RouteLocationRaw } from 'vue-router'
|
||||||
|
import { sendRedirect } from 'h3'
|
||||||
import { useNuxtApp } from '#app'
|
import { useNuxtApp } from '#app'
|
||||||
|
|
||||||
export const useRouter = () => {
|
export const useRouter = () => {
|
||||||
@ -45,12 +46,23 @@ const isProcessingMiddleware = () => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
export const navigateTo = (to: RouteLocationRaw) => {
|
export interface NavigateToOptions {
|
||||||
|
replace?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const navigateTo = (to: RouteLocationRaw, options: NavigateToOptions = {}) => {
|
||||||
if (isProcessingMiddleware()) {
|
if (isProcessingMiddleware()) {
|
||||||
return to
|
return to
|
||||||
}
|
}
|
||||||
const router: Router = process.server ? useRouter() : (window as any).$nuxt.$router
|
const router = useRouter()
|
||||||
return router.push(to)
|
if (process.server && useNuxtApp().ssrContext) {
|
||||||
|
// Server-side redirection using h3 res from ssrContext
|
||||||
|
const res = useNuxtApp().ssrContext?.res
|
||||||
|
const redirectLocation = router.resolve(to).fullPath
|
||||||
|
return sendRedirect(res, redirectLocation)
|
||||||
|
}
|
||||||
|
// Client-side redirection using vue-router
|
||||||
|
return options.replace ? router.replace(to) : router.push(to)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This will abort navigation within a Nuxt route middleware handler. */
|
/** This will abort navigation within a Nuxt route middleware handler. */
|
||||||
|
@ -94,6 +94,17 @@ describe('fixtures:basic', async () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('navigate', () => {
|
||||||
|
it('should redirect to index with navigateTo', async () => {
|
||||||
|
const html = await $fetch('/navigate-to/')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('Hello Nuxt 3!')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('middlewares', () => {
|
describe('middlewares', () => {
|
||||||
it('should redirect to index with global middleware', async () => {
|
it('should redirect to index with global middleware', async () => {
|
||||||
const html = await $fetch('/redirect/')
|
const html = await $fetch('/redirect/')
|
||||||
|
@ -8,7 +8,16 @@ describe('fixtures:bridge', async () => {
|
|||||||
server: true
|
server: true
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Render hello world', async () => {
|
describe('pages', () => {
|
||||||
|
it('render hello world', async () => {
|
||||||
expect(await $fetch('/')).to.contain('Hello Vue 2!')
|
expect(await $fetch('/')).to.contain('Hello Vue 2!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('navigate', () => {
|
||||||
|
it('should redirect to index with navigateTo', async () => {
|
||||||
|
const html = await $fetch('/navigate-to/')
|
||||||
|
expect(html).toContain('Hello Vue 2!')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
7
test/fixtures/basic/pages/navigate-to.vue
vendored
Normal file
7
test/fixtures/basic/pages/navigate-to.vue
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<div>You should not see me</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
navigateTo('/', { replace: true })
|
||||||
|
</script>
|
2
test/fixtures/basic/types.ts
vendored
2
test/fixtures/basic/types.ts
vendored
@ -51,7 +51,7 @@ describe('middleware', () => {
|
|||||||
addRouteMiddleware('example', (to, from) => {
|
addRouteMiddleware('example', (to, from) => {
|
||||||
expectTypeOf(to).toMatchTypeOf<RouteLocationNormalizedLoaded>()
|
expectTypeOf(to).toMatchTypeOf<RouteLocationNormalizedLoaded>()
|
||||||
expectTypeOf(from).toMatchTypeOf<RouteLocationNormalizedLoaded>()
|
expectTypeOf(from).toMatchTypeOf<RouteLocationNormalizedLoaded>()
|
||||||
expectTypeOf(navigateTo).toMatchTypeOf<(to: RouteLocationRaw) => RouteLocationRaw | Promise<void | NavigationFailure>>()
|
expectTypeOf(navigateTo).toMatchTypeOf<(to: RouteLocationRaw) => RouteLocationRaw | Promise<void | unknown | NavigationFailure>>()
|
||||||
navigateTo('/')
|
navigateTo('/')
|
||||||
abortNavigation()
|
abortNavigation()
|
||||||
abortNavigation('error string')
|
abortNavigation('error string')
|
||||||
|
7
test/fixtures/bridge/pages/navigate-to.vue
vendored
Normal file
7
test/fixtures/bridge/pages/navigate-to.vue
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<div>You should not see me</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
navigateTo('/', { replace: true })
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user