diff --git a/packages/nuxt3/src/app/composables/cookie.ts b/packages/nuxt3/src/app/composables/cookie.ts index d5f7bf1b48..4898b86b27 100644 --- a/packages/nuxt3/src/app/composables/cookie.ts +++ b/packages/nuxt3/src/app/composables/cookie.ts @@ -32,13 +32,14 @@ export function useCookie (name: string, _opts?: CookieOptions): 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 diff --git a/packages/nuxt3/src/app/composables/router.ts b/packages/nuxt3/src/app/composables/router.ts index e5b9c7199e..901ef43009 100644 --- a/packages/nuxt3/src/app/composables/router.ts +++ b/packages/nuxt3/src/app/composables/router.ts @@ -52,6 +52,7 @@ const isProcessingMiddleware = () => { export interface NavigateToOptions { replace?: boolean + redirectCode?: number } export const navigateTo = (to: RouteLocationRaw, options: NavigateToOptions = {}): Promise | 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 diff --git a/packages/nuxt3/src/app/nuxt.ts b/packages/nuxt3/src/app/nuxt.ts index 10c247d681..65d50a560b 100644 --- a/packages/nuxt3/src/app/nuxt.ts +++ b/packages/nuxt3/src/app/nuxt.ts @@ -23,6 +23,7 @@ export interface RuntimeNuxtHooks { 'app:beforeMount': (app: App) => HookResult 'app:mounted': (app: App) => 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 diff --git a/packages/nuxt3/src/app/plugins/router.ts b/packages/nuxt3/src/app/plugins/router.ts index f4cd7d88b4..3fcbc18d67 100644 --- a/packages/nuxt3/src/app/plugins/router.ts +++ b/packages/nuxt3/src/app/plugins/router.ts @@ -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) } }) } diff --git a/packages/nuxt3/src/pages/runtime/router.ts b/packages/nuxt3/src/pages/runtime/router.ts index fef1d3eeb5..79fcbf15ed 100644 --- a/packages/nuxt3/src/pages/runtime/router.ts +++ b/packages/nuxt3/src/pages/runtime/router.ts @@ -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) } }) }