fix(nuxt3): improve redirect lifecycle (#4430)

* fix(nuxt3): improve redirect lifecycle

* fix: check against existing cookie value in header
This commit is contained in:
Daniel Roe 2022-04-19 20:13:11 +01:00 committed by GitHub
parent 71b808c8e9
commit ea47e56540
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 16 additions and 17 deletions

View File

@ -32,13 +32,14 @@ export function useCookie <T=string> (name: string, _opts?: CookieOptions<T>): C
if (process.client) {
watch(cookie, () => { writeClientCookie(name, cookie.value, opts as CookieSerializeOptions) })
} else if (process.server) {
const initialValue = cookie.value
const nuxtApp = useNuxtApp()
nuxtApp.hooks.hookOnce('app:rendered', () => {
if (cookie.value !== initialValue) {
const writeFinalCookieValue = () => {
if (cookie.value !== cookies[name]) {
writeServerCookie(useRequestEvent(nuxtApp), name, cookie.value, opts)
}
})
}
nuxtApp.hooks.hookOnce('app:rendered', writeFinalCookieValue)
nuxtApp.hooks.hookOnce('app:redirected', writeFinalCookieValue)
}
return cookie as CookieRef<T>

View File

@ -52,6 +52,7 @@ const isProcessingMiddleware = () => {
export interface NavigateToOptions {
replace?: boolean
redirectCode?: number
}
export const navigateTo = (to: RouteLocationRaw, options: NavigateToOptions = {}): Promise<void | NavigationFailure> | RouteLocationRaw => {
@ -59,11 +60,11 @@ export const navigateTo = (to: RouteLocationRaw, options: NavigateToOptions = {}
return to
}
const router = useRouter()
if (process.server && useNuxtApp().ssrContext) {
const { ssrContext } = useNuxtApp()
if (ssrContext && ssrContext.event) {
if (process.server) {
const nuxtApp = useNuxtApp()
if (nuxtApp.ssrContext && nuxtApp.ssrContext.event) {
const redirectLocation = router.resolve(to).fullPath
return sendRedirect(ssrContext.event, redirectLocation)
return nuxtApp.callHook('app:redirected').then(() => sendRedirect(nuxtApp.ssrContext.event, redirectLocation, options.redirectCode || 301))
}
}
// Client-side redirection using vue-router

View File

@ -23,6 +23,7 @@ export interface RuntimeNuxtHooks {
'app:beforeMount': (app: App<Element>) => HookResult
'app:mounted': (app: App<Element>) => HookResult
'app:rendered': () => HookResult
'app:redirected': () => HookResult
'app:suspense:resolve': (Component?: VNode) => HookResult
'app:error': (err: any) => HookResult
'app:error:cleared': (options: { redirect?: string }) => HookResult

View File

@ -3,7 +3,7 @@ import { parseURL, parseQuery } from 'ufo'
import { createError } from 'h3'
import { defineNuxtPlugin } from '..'
import { callWithNuxt } from '../nuxt'
import { clearError, throwError } from '#app'
import { clearError, navigateTo, throwError } from '#app'
interface Route {
/** Percentage encoded pathname section of the URL. */
@ -221,9 +221,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
nuxtApp.hooks.hookOnce('app:created', async () => {
await router.push(nuxtApp.ssrContext.url)
if (route.fullPath !== nuxtApp.ssrContext.url) {
nuxtApp.ssrContext.res.setHeader('Location', route.fullPath)
nuxtApp.ssrContext.res.statusCode = 301
nuxtApp.ssrContext.res.end()
await navigateTo(route.fullPath)
}
})
}

View File

@ -9,7 +9,7 @@ import {
import { createError } from 'h3'
import { withoutBase } from 'ufo'
import NuxtPage from './page'
import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, throwError, clearError } from '#app'
import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, throwError, clearError, navigateTo } from '#app'
// @ts-ignore
import routes from '#build/routes'
// @ts-ignore
@ -167,11 +167,9 @@ export default defineNuxtPlugin((nuxtApp) => {
if (process.server) {
router.push(nuxtApp.ssrContext.url)
router.afterEach((to) => {
router.afterEach(async (to) => {
if (to.fullPath !== nuxtApp.ssrContext.url) {
nuxtApp.ssrContext.res.setHeader('Location', to.fullPath)
nuxtApp.ssrContext.res.statusCode = 301
nuxtApp.ssrContext.res.end()
await navigateTo(to.fullPath)
}
})
}