mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 05:35:13 +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) => {
|
export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
||||||
|
const initialURL = process.client ? window.location.href : nuxtApp.ssrContext.url
|
||||||
const routes = []
|
const routes = []
|
||||||
|
|
||||||
const hooks: { [key in keyof RouterHooks]: RouterHooks[key][] } = {
|
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)
|
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> {
|
async function handleNavigation (url: string, replace?: boolean): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Resolve route
|
// Resolve route
|
||||||
@ -193,38 +194,36 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
|||||||
named: {}
|
named: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
router.beforeEach(async (to, from) => {
|
nuxtApp.hooks.hookOnce('app:created', async () => {
|
||||||
to.meta = reactive(to.meta || {})
|
router.beforeEach(async (to, from) => {
|
||||||
nuxtApp._processingMiddleware = true
|
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) {
|
for (const middleware of middlewareEntries) {
|
||||||
const result = await callWithNuxt(nuxtApp, middleware, [to, from])
|
const result = await callWithNuxt(nuxtApp, middleware, [to, from])
|
||||||
if (process.server) {
|
if (process.server) {
|
||||||
if (result === false || result instanceof Error) {
|
if (result === false || result instanceof Error) {
|
||||||
const error = result || createError({
|
const error = result || createError({
|
||||||
statusMessage: `Route navigation aborted: ${nuxtApp.ssrContext.url}`
|
statusMessage: `Route navigation aborted: ${initialURL}`
|
||||||
})
|
})
|
||||||
return callWithNuxt(nuxtApp, throwError, [error])
|
return callWithNuxt(nuxtApp, throwError, [error])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (result || result === false) { return result }
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
router.afterEach(() => {
|
||||||
|
delete nuxtApp._processingMiddleware
|
||||||
|
})
|
||||||
|
|
||||||
|
await router.replace(initialURL)
|
||||||
|
if (route.fullPath !== initialURL) {
|
||||||
|
await callWithNuxt(nuxtApp, navigateTo, [route.fullPath])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
provide: {
|
provide: {
|
||||||
|
@ -48,7 +48,7 @@ function createCurrentLocation (
|
|||||||
return path + search + hash
|
return path + search + hash
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||||
nuxtApp.vueApp.component('NuxtPage', NuxtPage)
|
nuxtApp.vueApp.component('NuxtPage', NuxtPage)
|
||||||
// TODO: remove before release - present for backwards compatibility & intentionally undocumented
|
// TODO: remove before release - present for backwards compatibility & intentionally undocumented
|
||||||
nuxtApp.vueApp.component('NuxtNestedPage', NuxtPage)
|
nuxtApp.vueApp.component('NuxtNestedPage', NuxtPage)
|
||||||
@ -59,6 +59,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
? createWebHistory(baseURL)
|
? createWebHistory(baseURL)
|
||||||
: createMemoryHistory(baseURL)
|
: createMemoryHistory(baseURL)
|
||||||
|
|
||||||
|
const initialURL = process.server ? nuxtApp.ssrContext.url : createCurrentLocation(baseURL, window.location)
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
...routerOptions,
|
...routerOptions,
|
||||||
history: routerHistory,
|
history: routerHistory,
|
||||||
@ -82,8 +83,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allows suspending the route object until page navigation completes
|
// 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(initialURL) as RouteLocation)
|
||||||
const _activeRoute = shallowRef(router.resolve(path) as RouteLocation)
|
|
||||||
const syncCurrentRoute = () => { _activeRoute.value = router.currentRoute.value }
|
const syncCurrentRoute = () => { _activeRoute.value = router.currentRoute.value }
|
||||||
nuxtApp.hook('page:finish', syncCurrentRoute)
|
nuxtApp.hook('page:finish', syncCurrentRoute)
|
||||||
router.afterEach((to, from) => {
|
router.afterEach((to, from) => {
|
||||||
@ -107,6 +107,28 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
named: {}
|
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) => {
|
router.beforeEach(async (to, from) => {
|
||||||
to.meta = reactive(to.meta)
|
to.meta = reactive(to.meta)
|
||||||
nuxtApp._processingMiddleware = true
|
nuxtApp._processingMiddleware = true
|
||||||
@ -141,7 +163,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
if (process.server) {
|
if (process.server) {
|
||||||
if (result === false || result instanceof Error) {
|
if (result === false || result instanceof Error) {
|
||||||
const error = result || createError({
|
const error = result || createError({
|
||||||
statusMessage: `Route navigation aborted: ${nuxtApp.ssrContext.url}`
|
statusMessage: `Route navigation aborted: ${initialURL}`
|
||||||
})
|
})
|
||||||
return callWithNuxt(nuxtApp, throwError, [error])
|
return callWithNuxt(nuxtApp, throwError, [error])
|
||||||
}
|
}
|
||||||
@ -150,37 +172,24 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.afterEach(() => {
|
router.afterEach(async (to) => {
|
||||||
delete nuxtApp._processingMiddleware
|
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) {
|
if (process.server) {
|
||||||
router.afterEach(async (to) => {
|
if (to.fullPath !== initialURL) {
|
||||||
if (to.fullPath !== nuxtApp.ssrContext.url) {
|
await callWithNuxt(nuxtApp, navigateTo, [to.fullPath])
|
||||||
await navigateTo(to.fullPath)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (process.server) {
|
|
||||||
await router.push(nuxtApp.ssrContext.url)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
await router.isReady()
|
nuxtApp.hooks.hookOnce('app:created', async () => {
|
||||||
|
try {
|
||||||
|
await router.replace({
|
||||||
|
path: initialURL,
|
||||||
|
force: true
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// We'll catch middleware errors or deliberate exceptions here
|
||||||
callWithNuxt(nuxtApp, throwError, [error])
|
callWithNuxt(nuxtApp, throwError, [error])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
export default defineNuxtRouteMiddleware(async (to) => {
|
export default defineNuxtRouteMiddleware(async (to) => {
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
if (to.path.startsWith('/redirect/')) {
|
if (to.path.startsWith('/redirect/')) {
|
||||||
await new Promise(resolve => setTimeout(resolve, 100))
|
await new Promise(resolve => setTimeout(resolve, 100))
|
||||||
return navigateTo(to.path.slice('/redirect/'.length - 1))
|
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({
|
useHead({
|
||||||
titleTemplate: '%s - Fixture'
|
titleTemplate: '%s - Fixture'
|
||||||
})
|
})
|
||||||
|
const path = useRoute().path
|
||||||
return {
|
return {
|
||||||
provide: {
|
provide: {
|
||||||
myPlugin: () => 'Injected by my-plugin'
|
myPlugin: () => 'Injected by my-plugin',
|
||||||
|
path: () => path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user