From ce3b51645feb1efd5e90c87f733945ebd49a0fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Pe=C5=A1i=C4=87?= Date: Sat, 14 Feb 2026 00:44:13 +0100 Subject: [PATCH 1/2] fix(router): fix middleware and plugin ordering --- playground/plugins/auth.ts | 3 +++ src/runtime/plugins/router.ts | 47 ++++++++++++++++------------------- test/e2e/ssr.spec.ts | 22 ++++++++++++++++ 3 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 playground/plugins/auth.ts diff --git a/playground/plugins/auth.ts b/playground/plugins/auth.ts new file mode 100644 index 00000000..cc104c8f --- /dev/null +++ b/playground/plugins/auth.ts @@ -0,0 +1,3 @@ +export default defineNuxtPlugin(() => { + console.log('ran plugin') +}) diff --git a/src/runtime/plugins/router.ts b/src/runtime/plugins/router.ts index 9ef98878..9df8b6cd 100644 --- a/src/runtime/plugins/router.ts +++ b/src/runtime/plugins/router.ts @@ -15,7 +15,6 @@ import type { PageMeta, Plugin, RouteMiddleware } from '#app' import { getRouteRules } from '#app/composables/manifest' import { defineNuxtPlugin, useRuntimeConfig } from '#app/nuxt' import { clearError, showError, useError } from '#app/composables/error' -import { onNuxtReady } from '#app/composables/ready' import { navigateTo } from '#app/composables/router' // @ts-expect-error virtual file @@ -141,14 +140,36 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({ } const initialLayout = nuxtApp.payload.state._layout + + const pluginsReady = new Promise((resolve) => { + nuxtApp.hooks.hookOnce('app:created', async () => { + delete nuxtApp._processingMiddleware + resolve() + }) + }) + + let needsCorrection = import.meta.client + router.beforeEach(async (to, from) => { + // wait for plugins to finish + await pluginsReady await nuxtApp.callHook('page:loading:start') + to.meta = reactive(to.meta) if (nuxtApp.isHydrating && initialLayout && !isReadonly(to.meta.layout)) { to.meta.layout = initialLayout as Exclude } nuxtApp._processingMiddleware = true + if (needsCorrection) { + needsCorrection = false + // #4920, #4982 + if ('name' in resolvedInitialRoute) { + resolvedInitialRoute.name = undefined + } + return { ...resolvedInitialRoute, replace: true } + } + if (import.meta.client || !nuxtApp.ssrContext?.islandContext) { type MiddlewareDef = string | RouteMiddleware const middlewareEntries = new Set([...globalMiddleware, ...nuxtApp._middleware.global]) @@ -219,30 +240,6 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({ await nuxtApp.callHook('page:loading:end') }) - nuxtApp.hooks.hookOnce('app:created', async () => { - delete nuxtApp._processingMiddleware - }) - - onNuxtReady(async () => { - try { - if (import.meta.client) { - // #4920, #4982 - if ('name' in resolvedInitialRoute) { - resolvedInitialRoute.name = undefined - } - await router.replace({ - ...resolvedInitialRoute, - force: true, - }) - } - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - catch (error: any) { - // We'll catch middleware errors or deliberate exceptions here - await nuxtApp.runWithContext(() => showError(error)) - } - }) - return { provide: { router } } }, }) diff --git a/test/e2e/ssr.spec.ts b/test/e2e/ssr.spec.ts index 992fe45e..0b0a36f6 100644 --- a/test/e2e/ssr.spec.ts +++ b/test/e2e/ssr.spec.ts @@ -36,4 +36,26 @@ describe('nuxt ionic', async () => { await page.close() }) + + it('runs plugin and middleware in correct order', async () => { + const logs: string[] = [] + const page = await createPage() + page.on('console', (msg) => { + logs.push(msg.text()) + }) + await page.goto(url('/tabs/tab1')) + await page.waitForLoadState('networkidle') + + expect(logs).toContain('ran plugin') + expect(logs).toContain('ran middleware') + + // Plugin should run before middleware + const pluginIndex = logs.indexOf('ran plugin') + const middlewareIndex = logs.indexOf('ran middleware') + expect(pluginIndex).toBeGreaterThanOrEqual(0) + expect(middlewareIndex).toBeGreaterThanOrEqual(0) + expect(pluginIndex).toBeLessThan(middlewareIndex) + + await page.close() + }) }) From 5dbf9e96fa54dca0c2b72b2437b45fc4c367191d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Pe=C5=A1i=C4=87?= Date: Sun, 15 Feb 2026 20:18:32 +0100 Subject: [PATCH 2/2] fix(router): no route on landing --- playground/pages/tabs/tab1/index.vue | 4 +++ src/runtime/plugins/router.ts | 6 +++- test/e2e/ssr.spec.ts | 42 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/playground/pages/tabs/tab1/index.vue b/playground/pages/tabs/tab1/index.vue index 0ac63c50..04160685 100644 --- a/playground/pages/tabs/tab1/index.vue +++ b/playground/pages/tabs/tab1/index.vue @@ -6,6 +6,10 @@ useHead({ title: 'Tab 1', }) const isExploreEnabled = ref(true) + +const route = useRoute() + +console.log(route.name)