mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
fix(nuxt): process middleware after plugins (#4645)
This commit is contained in:
parent
82f959d91f
commit
4826918ed0
@ -86,6 +86,7 @@ interface Router {
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
||||
const initialURL = process.client ? window.location.href : nuxtApp.ssrContext.url
|
||||
const routes = []
|
||||
|
||||
const hooks: { [key in keyof RouterHooks]: RouterHooks[key][] } = {
|
||||
@ -100,7 +101,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
||||
return () => hooks[hook].splice(hooks[hook].indexOf(guard), 1)
|
||||
}
|
||||
|
||||
const route: Route = reactive(getRouteFromPath(process.client ? window.location.href : nuxtApp.ssrContext.url))
|
||||
const route: Route = reactive(getRouteFromPath(initialURL))
|
||||
async function handleNavigation (url: string, replace?: boolean): Promise<void> {
|
||||
try {
|
||||
// Resolve route
|
||||
@ -193,38 +194,36 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
||||
named: {}
|
||||
}
|
||||
|
||||
router.beforeEach(async (to, from) => {
|
||||
to.meta = reactive(to.meta || {})
|
||||
nuxtApp._processingMiddleware = true
|
||||
nuxtApp.hooks.hookOnce('app:created', async () => {
|
||||
router.beforeEach(async (to, from) => {
|
||||
to.meta = reactive(to.meta || {})
|
||||
nuxtApp._processingMiddleware = true
|
||||
|
||||
const middlewareEntries = new Set<RouteGuard>(nuxtApp._middleware.global)
|
||||
const middlewareEntries = new Set<RouteGuard>(nuxtApp._middleware.global)
|
||||
|
||||
for (const middleware of middlewareEntries) {
|
||||
const result = await callWithNuxt(nuxtApp, middleware, [to, from])
|
||||
if (process.server) {
|
||||
if (result === false || result instanceof Error) {
|
||||
const error = result || createError({
|
||||
statusMessage: `Route navigation aborted: ${nuxtApp.ssrContext.url}`
|
||||
})
|
||||
return callWithNuxt(nuxtApp, throwError, [error])
|
||||
for (const middleware of middlewareEntries) {
|
||||
const result = await callWithNuxt(nuxtApp, middleware, [to, from])
|
||||
if (process.server) {
|
||||
if (result === false || result instanceof Error) {
|
||||
const error = result || createError({
|
||||
statusMessage: `Route navigation aborted: ${initialURL}`
|
||||
})
|
||||
return callWithNuxt(nuxtApp, throwError, [error])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result || result === false) { return result }
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(() => {
|
||||
delete nuxtApp._processingMiddleware
|
||||
})
|
||||
|
||||
if (process.server) {
|
||||
nuxtApp.hooks.hookOnce('app:created', async () => {
|
||||
await router.push(nuxtApp.ssrContext.url)
|
||||
if (route.fullPath !== nuxtApp.ssrContext.url) {
|
||||
await navigateTo(route.fullPath)
|
||||
if (result || result === false) { return result }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
router.afterEach(() => {
|
||||
delete nuxtApp._processingMiddleware
|
||||
})
|
||||
|
||||
await router.replace(initialURL)
|
||||
if (route.fullPath !== initialURL) {
|
||||
await callWithNuxt(nuxtApp, navigateTo, [route.fullPath])
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
provide: {
|
||||
|
@ -48,7 +48,7 @@ function createCurrentLocation (
|
||||
return path + search + hash
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||
nuxtApp.vueApp.component('NuxtPage', NuxtPage)
|
||||
// TODO: remove before release - present for backwards compatibility & intentionally undocumented
|
||||
nuxtApp.vueApp.component('NuxtNestedPage', NuxtPage)
|
||||
@ -59,6 +59,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
? createWebHistory(baseURL)
|
||||
: createMemoryHistory(baseURL)
|
||||
|
||||
const initialURL = process.server ? nuxtApp.ssrContext.url : createCurrentLocation(baseURL, window.location)
|
||||
const router = createRouter({
|
||||
...routerOptions,
|
||||
history: routerHistory,
|
||||
@ -82,8 +83,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
}
|
||||
|
||||
// Allows suspending the route object until page navigation completes
|
||||
const path = process.server ? nuxtApp.ssrContext.url : createCurrentLocation(baseURL, window.location)
|
||||
const _activeRoute = shallowRef(router.resolve(path) as RouteLocation)
|
||||
const _activeRoute = shallowRef(router.resolve(initialURL) as RouteLocation)
|
||||
const syncCurrentRoute = () => { _activeRoute.value = router.currentRoute.value }
|
||||
nuxtApp.hook('page:finish', syncCurrentRoute)
|
||||
router.afterEach((to, from) => {
|
||||
@ -107,6 +107,28 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
named: {}
|
||||
}
|
||||
|
||||
router.afterEach((to) => {
|
||||
if (to.matched.length === 0) {
|
||||
callWithNuxt(nuxtApp, throwError, [createError({
|
||||
statusCode: 404,
|
||||
statusMessage: `Page not found: ${to.fullPath}`
|
||||
})])
|
||||
} else if (process.server && to.matched[0].name === '404' && nuxtApp.ssrContext) {
|
||||
nuxtApp.ssrContext.res.statusCode = 404
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
if (process.server) {
|
||||
await router.push(initialURL)
|
||||
}
|
||||
|
||||
await router.isReady()
|
||||
} catch (error) {
|
||||
// We'll catch 404s here
|
||||
callWithNuxt(nuxtApp, throwError, [error])
|
||||
}
|
||||
|
||||
router.beforeEach(async (to, from) => {
|
||||
to.meta = reactive(to.meta)
|
||||
nuxtApp._processingMiddleware = true
|
||||
@ -141,7 +163,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
if (process.server) {
|
||||
if (result === false || result instanceof Error) {
|
||||
const error = result || createError({
|
||||
statusMessage: `Route navigation aborted: ${nuxtApp.ssrContext.url}`
|
||||
statusMessage: `Route navigation aborted: ${initialURL}`
|
||||
})
|
||||
return callWithNuxt(nuxtApp, throwError, [error])
|
||||
}
|
||||
@ -150,37 +172,24 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(() => {
|
||||
router.afterEach(async (to) => {
|
||||
delete nuxtApp._processingMiddleware
|
||||
})
|
||||
|
||||
nuxtApp.hook('app:created', async () => {
|
||||
router.afterEach((to) => {
|
||||
if (to.matched.length === 0) {
|
||||
callWithNuxt(nuxtApp, throwError, [createError({
|
||||
statusCode: 404,
|
||||
statusMessage: `Page not found: ${to.fullPath}`
|
||||
})])
|
||||
} else if (process.server && to.matched[0].name === '404' && nuxtApp.ssrContext) {
|
||||
nuxtApp.ssrContext.res.statusCode = 404
|
||||
}
|
||||
})
|
||||
|
||||
if (process.server) {
|
||||
router.afterEach(async (to) => {
|
||||
if (to.fullPath !== nuxtApp.ssrContext.url) {
|
||||
await navigateTo(to.fullPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
if (process.server) {
|
||||
await router.push(nuxtApp.ssrContext.url)
|
||||
if (to.fullPath !== initialURL) {
|
||||
await callWithNuxt(nuxtApp, navigateTo, [to.fullPath])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
await router.isReady()
|
||||
nuxtApp.hooks.hookOnce('app:created', async () => {
|
||||
try {
|
||||
await router.replace({
|
||||
path: initialURL,
|
||||
force: true
|
||||
})
|
||||
} catch (error) {
|
||||
// We'll catch middleware errors or deliberate exceptions here
|
||||
callWithNuxt(nuxtApp, throwError, [error])
|
||||
}
|
||||
})
|
||||
|
@ -1,6 +1,11 @@
|
||||
export default defineNuxtRouteMiddleware(async (to) => {
|
||||
const nuxtApp = useNuxtApp()
|
||||
if (to.path.startsWith('/redirect/')) {
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
return navigateTo(to.path.slice('/redirect/'.length - 1))
|
||||
}
|
||||
const pluginPath = nuxtApp.$path()
|
||||
if (process.server && !/redirect|navigate/.test(pluginPath) && to.path !== pluginPath) {
|
||||
throw new Error('plugin did not run before middleware')
|
||||
}
|
||||
})
|
||||
|
4
test/fixtures/basic/plugins/my-plugin.ts
vendored
4
test/fixtures/basic/plugins/my-plugin.ts
vendored
@ -2,9 +2,11 @@ export default defineNuxtPlugin(() => {
|
||||
useHead({
|
||||
titleTemplate: '%s - Fixture'
|
||||
})
|
||||
const path = useRoute().path
|
||||
return {
|
||||
provide: {
|
||||
myPlugin: () => 'Injected by my-plugin'
|
||||
myPlugin: () => 'Injected by my-plugin',
|
||||
path: () => path
|
||||
}
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user