Skip to content

Commit edf45ab

Browse files
committed
fix: register and run middleware after app mounts
resolves #287
1 parent ff44749 commit edf45ab

File tree

1 file changed

+90
-75
lines changed

1 file changed

+90
-75
lines changed

src/runtime/router.ts

Lines changed: 90 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -89,94 +89,109 @@ export default defineNuxtPlugin(async nuxtApp => {
8989

9090
const error = useError()
9191

92-
const initialLayout = useState<string>('_layout')
93-
router.beforeEach(async (to, from) => {
94-
to.meta = reactive(to.meta)
95-
if (nuxtApp.isHydrating && initialLayout.value && !isReadonly(to.meta.layout)) {
96-
to.meta.layout = initialLayout.value as Exclude<PageMeta['layout'], Ref | false>
97-
}
98-
nuxtApp._processingMiddleware = true
99-
100-
type MiddlewareDef = string | RouteMiddleware
101-
const middlewareEntries = new Set<MiddlewareDef>([
102-
...globalMiddleware,
103-
...nuxtApp._middleware.global,
104-
])
105-
for (const component of to.matched) {
106-
const componentMiddleware = component.meta.middleware as MiddlewareDef | MiddlewareDef[]
107-
if (!componentMiddleware) {
108-
continue
92+
nuxtApp.hooks.hookOnce('app:mounted', async () => {
93+
const initialLayout = useState<string>('_layout')
94+
router.beforeEach(async (to, from) => {
95+
to.meta = reactive(to.meta)
96+
if (nuxtApp.isHydrating && initialLayout.value && !isReadonly(to.meta.layout)) {
97+
to.meta.layout = initialLayout.value as Exclude<PageMeta['layout'], Ref | false>
10998
}
110-
if (Array.isArray(componentMiddleware)) {
111-
for (const entry of componentMiddleware) {
112-
middlewareEntries.add(entry)
99+
nuxtApp._processingMiddleware = true
100+
101+
type MiddlewareDef = string | RouteMiddleware
102+
const middlewareEntries = new Set<MiddlewareDef>([
103+
...globalMiddleware,
104+
...nuxtApp._middleware.global,
105+
])
106+
for (const component of to.matched) {
107+
const componentMiddleware = component.meta.middleware as MiddlewareDef | MiddlewareDef[]
108+
if (!componentMiddleware) {
109+
continue
110+
}
111+
if (Array.isArray(componentMiddleware)) {
112+
for (const entry of componentMiddleware) {
113+
middlewareEntries.add(entry)
114+
}
115+
} else {
116+
middlewareEntries.add(componentMiddleware)
113117
}
114-
} else {
115-
middlewareEntries.add(componentMiddleware)
116118
}
117-
}
118119

119-
for (const entry of middlewareEntries) {
120-
const middleware =
121-
typeof entry === 'string'
122-
? nuxtApp._middleware.named[entry] ||
120+
for (const entry of middlewareEntries) {
121+
const middleware =
122+
typeof entry === 'string'
123+
? nuxtApp._middleware.named[entry] ||
123124
(await namedMiddleware[entry]?.().then((r: any) => r.default || r))
124-
: entry
125-
126-
if (!middleware) {
127-
if (process.dev) {
128-
throw new Error(
129-
`Unknown route middleware: '${entry}'. Valid middleware: ${Object.keys(namedMiddleware)
130-
.map(mw => `'${mw}'`)
131-
.join(', ')}.`
132-
)
125+
: entry
126+
127+
if (!middleware) {
128+
if (process.dev) {
129+
throw new Error(
130+
`Unknown route middleware: '${entry}'. Valid middleware: ${Object.keys(namedMiddleware)
131+
.map(mw => `'${mw}'`)
132+
.join(', ')}.`
133+
)
134+
}
135+
throw new Error(`Unknown route middleware: '${entry}'.`)
133136
}
134-
throw new Error(`Unknown route middleware: '${entry}'.`)
135-
}
136137

137-
const result = await callWithNuxt(nuxtApp, middleware, [to, from])
138-
if (process.server || (!nuxtApp.payload.serverRendered && nuxtApp.isHydrating)) {
139-
if (result === false || result instanceof Error) {
140-
const error =
141-
result ||
142-
createError({
143-
statusCode: 404,
144-
statusMessage: `Page Not Found: ${initialURL}`,
145-
})
146-
await callWithNuxt(nuxtApp, showError, [error])
147-
return false
138+
const result = await callWithNuxt(nuxtApp, middleware, [to, from])
139+
if (process.server || (!nuxtApp.payload.serverRendered && nuxtApp.isHydrating)) {
140+
if (result === false || result instanceof Error) {
141+
const error =
142+
result ||
143+
createError({
144+
statusCode: 404,
145+
statusMessage: `Page Not Found: ${initialURL}`,
146+
})
147+
await callWithNuxt(nuxtApp, showError, [error])
148+
return false
149+
}
150+
}
151+
if (result || result === false) {
152+
return result
148153
}
149154
}
150-
if (result || result === false) {
151-
return result
152-
}
153-
}
154-
})
155+
})
155156

156-
router.afterEach(async to => {
157-
delete nuxtApp._processingMiddleware
157+
router.afterEach(async to => {
158+
delete nuxtApp._processingMiddleware
158159

159-
if (process.client && !nuxtApp.isHydrating && error.value) {
160-
// Clear any existing errors
161-
await callWithNuxt(nuxtApp, clearError)
162-
}
163-
if (to.matched.length === 0) {
164-
await callWithNuxt(nuxtApp, showError, [
165-
createError({
166-
statusCode: 404,
167-
fatal: false,
168-
statusMessage: `Page not found: ${to.fullPath}`,
169-
}),
170-
])
171-
} else if (process.server) {
172-
const currentURL = to.fullPath || '/'
173-
if (!isEqual(currentURL, initialURL, { trailingSlash: true })) {
174-
const event = await callWithNuxt(nuxtApp, useRequestEvent)
175-
const options = {
176-
redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302,
160+
if (process.client && !nuxtApp.isHydrating && error.value) {
161+
// Clear any existing errors
162+
await callWithNuxt(nuxtApp, clearError)
163+
}
164+
if (to.matched.length === 0) {
165+
await callWithNuxt(nuxtApp, showError, [
166+
createError({
167+
statusCode: 404,
168+
fatal: false,
169+
statusMessage: `Page not found: ${to.fullPath}`,
170+
}),
171+
])
172+
} else if (process.server) {
173+
const currentURL = to.fullPath || '/'
174+
if (!isEqual(currentURL, initialURL, { trailingSlash: true })) {
175+
const event = await callWithNuxt(nuxtApp, useRequestEvent)
176+
const options = {
177+
redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302,
178+
}
179+
await callWithNuxt(nuxtApp, navigateTo, [currentURL, options])
177180
}
178-
await callWithNuxt(nuxtApp, navigateTo, [currentURL, options])
179181
}
182+
})
183+
184+
try {
185+
if (process.client) {
186+
await router.replace({
187+
...router.resolve(initialURL),
188+
name: undefined, // #4920, #4982
189+
force: true
190+
})
191+
}
192+
} catch (error: any) {
193+
// We'll catch middleware errors or deliberate exceptions here
194+
await nuxtApp.runWithContext(() => showError(error))
180195
}
181196
})
182197

0 commit comments

Comments
 (0)