Skip to content

Commit b35c642

Browse files
committed
fix: load ionic router before other plugins using explicit order
resolves #484 closes #470
1 parent 1fd0747 commit b35c642

File tree

1 file changed

+155
-151
lines changed

1 file changed

+155
-151
lines changed

src/runtime/router.ts

Lines changed: 155 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -26,180 +26,184 @@ import routerOptions from '#build/router.options'
2626
// @ts-expect-error virtual module generated by Nuxt
2727
import _routes from '#build/routes'
2828

29-
export default defineNuxtPlugin(async nuxtApp => {
30-
let routerBase = useRuntimeConfig().app.baseURL
31-
if (routerOptions.hashMode && !routerBase.includes('#')) {
32-
// allow the user to provide a `#` in the middle: `/base/#/app`
33-
routerBase += '#'
34-
}
29+
export default defineNuxtPlugin({
30+
name: 'nuxt:ionic:router',
31+
enforce: 'pre',
32+
setup(nuxtApp) {
33+
let routerBase = useRuntimeConfig().app.baseURL
34+
if (routerOptions.hashMode && !routerBase.includes('#')) {
35+
// allow the user to provide a `#` in the middle: `/base/#/app`
36+
routerBase += '#'
37+
}
3538

36-
const history =
37-
routerOptions.history?.(routerBase) ??
38-
(process.client
39-
? routerOptions.hashMode
40-
? createWebHashHistory(routerBase)
41-
: createWebHistory(routerBase)
42-
: createMemoryHistory(routerBase))
43-
44-
const routes = routerOptions.routes?.(_routes) ?? _routes
45-
46-
const initialURL = process.server
47-
? nuxtApp.ssrContext!.url
48-
: createCurrentLocation(routerBase, window.location)
49-
const router = createRouter({
50-
...routerOptions,
51-
history,
52-
routes,
53-
})
54-
nuxtApp.vueApp.use(router)
55-
const previousRoute = shallowRef(router.currentRoute.value)
56-
router.afterEach((_to, from) => {
57-
previousRoute.value = from
58-
})
59-
60-
Object.defineProperty(nuxtApp.vueApp.config.globalProperties, 'previousRoute', {
61-
get: () => previousRoute.value,
62-
})
63-
64-
// Allows suspending the route object until page navigation completes
65-
const _route = shallowRef(router.resolve(initialURL) as RouteLocation)
66-
const syncCurrentRoute = () => {
67-
_route.value = router.currentRoute.value
68-
}
69-
nuxtApp.hook('page:finish', syncCurrentRoute)
70-
router.afterEach((to, from) => {
71-
// We won't trigger suspense if the component is reused between routes
72-
// so we need to update the route manually
73-
if (to.matched[0]?.components?.default === from.matched[0]?.components?.default) {
74-
syncCurrentRoute()
39+
const history =
40+
routerOptions.history?.(routerBase) ??
41+
(process.client
42+
? routerOptions.hashMode
43+
? createWebHashHistory(routerBase)
44+
: createWebHistory(routerBase)
45+
: createMemoryHistory(routerBase))
46+
47+
const routes = routerOptions.routes?.(_routes) ?? _routes
48+
49+
const initialURL = process.server
50+
? nuxtApp.ssrContext!.url
51+
: createCurrentLocation(routerBase, window.location)
52+
const router = createRouter({
53+
...routerOptions,
54+
history,
55+
routes,
56+
})
57+
nuxtApp.vueApp.use(router)
58+
const previousRoute = shallowRef(router.currentRoute.value)
59+
router.afterEach((_to, from) => {
60+
previousRoute.value = from
61+
})
62+
63+
Object.defineProperty(nuxtApp.vueApp.config.globalProperties, 'previousRoute', {
64+
get: () => previousRoute.value,
65+
})
66+
67+
// Allows suspending the route object until page navigation completes
68+
const _route = shallowRef(router.resolve(initialURL) as RouteLocation)
69+
const syncCurrentRoute = () => {
70+
_route.value = router.currentRoute.value
7571
}
76-
})
72+
nuxtApp.hook('page:finish', syncCurrentRoute)
73+
router.afterEach((to, from) => {
74+
// We won't trigger suspense if the component is reused between routes
75+
// so we need to update the route manually
76+
if (to.matched[0]?.components?.default === from.matched[0]?.components?.default) {
77+
syncCurrentRoute()
78+
}
79+
})
7780

78-
// https://github.com/vuejs/router/blob/main/packages/router/src/router.ts#L1225-L1233
79-
const route = {} as { [K in keyof RouteLocation]: ComputedRef<RouteLocation[K]> }
80-
for (const key in _route.value) {
81-
route[key as 'path'] = computed(() => _route.value[key as 'path'])
82-
}
81+
// https://github.com/vuejs/router/blob/main/packages/router/src/router.ts#L1225-L1233
82+
const route = {} as { [K in keyof RouteLocation]: ComputedRef<RouteLocation[K]> }
83+
for (const key in _route.value) {
84+
route[key as 'path'] = computed(() => _route.value[key as 'path'])
85+
}
8386

84-
nuxtApp._route = reactive(route)
87+
nuxtApp._route = reactive(route)
8588

86-
nuxtApp._middleware = nuxtApp._middleware || {
87-
global: [],
88-
named: {},
89-
}
89+
nuxtApp._middleware = nuxtApp._middleware || {
90+
global: [],
91+
named: {},
92+
}
9093

91-
const error = useError()
94+
const error = useError()
9295

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

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

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

160-
router.afterEach(async to => {
161-
delete nuxtApp._processingMiddleware
163+
router.afterEach(async to => {
164+
delete nuxtApp._processingMiddleware
162165

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

188-
try {
189-
if (process.client) {
190-
await router.replace({
191-
...router.resolve(initialURL),
192-
name: undefined, // #4920, #4982
193-
force: true,
194-
})
195-
}
196-
} catch (error: any) {
197-
// We'll catch middleware errors or deliberate exceptions here
198-
await nuxtApp.runWithContext(() => showError(error))
199-
}
200-
})
201-
202-
return { provide: { router } }
205+
return { provide: { router } }
206+
},
203207
}) as Plugin<{ router: Router }>
204208

205209
// https://github.com/vuejs/router/blob/4a0cc8b9c1e642cdf47cc007fa5bbebde70afc66/packages/router/src/history/html5.ts#L37

0 commit comments

Comments
 (0)