diff --git a/packages/frontend-2/.cursor/rules/nuxt-patterns.mdc b/packages/frontend-2/.cursor/rules/nuxt-patterns.mdc
index e21d610a5..e17733f50 100644
--- a/packages/frontend-2/.cursor/rules/nuxt-patterns.mdc
+++ b/packages/frontend-2/.cursor/rules/nuxt-patterns.mdc
@@ -88,12 +88,12 @@ export default defineNuxtPlugin(() => {
```typescript
// middleware/auth.ts (route middleware)
-export default defineNuxtRouteMiddleware((to, from) => {
+export default defineParallelizedNuxtRouteMiddleware((to, from) => {
// Route protection logic
})
// middleware/global.global.ts (global middleware)
-export default defineNuxtRouteMiddleware((to, from) => {
+export default defineParallelizedNuxtRouteMiddleware((to, from) => {
// Runs on every route change
})
```
diff --git a/packages/frontend-2/components/error/page/GenericErrorBlock.vue b/packages/frontend-2/components/error/page/GenericErrorBlock.vue
index cfd0c11b2..161410b02 100644
--- a/packages/frontend-2/components/error/page/GenericErrorBlock.vue
+++ b/packages/frontend-2/components/error/page/GenericErrorBlock.vue
@@ -14,9 +14,10 @@
+ class="whitespace-pre-line font-mono max-w-xl text-body-xs text-foreground-2"
+ >
+ {{ error.stack.trim() }}
+
Go home
diff --git a/packages/frontend-2/components/project/model-page/versions/CardActions.vue b/packages/frontend-2/components/project/model-page/versions/CardActions.vue
index aa17b835e..b5dbd2ffd 100644
--- a/packages/frontend-2/components/project/model-page/versions/CardActions.vue
+++ b/packages/frontend-2/components/project/model-page/versions/CardActions.vue
@@ -4,6 +4,7 @@
diff --git a/packages/frontend-2/lib/core/helpers/middleware.ts b/packages/frontend-2/lib/core/helpers/middleware.ts
new file mode 100644
index 000000000..95528032c
--- /dev/null
+++ b/packages/frontend-2/lib/core/helpers/middleware.ts
@@ -0,0 +1,68 @@
+import type { RouteMiddleware } from '#app'
+import type { NavigationGuardReturn } from '#vue-router'
+import { isUndefinedOrVoid } from '@speckle/shared'
+import { useScopedState } from '~/lib/common/composables/scopedState'
+
+const useMiddlewareParallelizationState = () =>
+ useScopedState('middleware_parallelization', () => ({
+ middlewares: [] as Array<() => Promise>
+ }))
+
+/**
+ * Make the middleware process in parallel with other middlewares and only get fully awaited at the end
+ */
+const withParallelization = (middleware: RouteMiddleware): RouteMiddleware => {
+ return (...args) => {
+ const app = useNuxtApp()
+ const {
+ public: { parallelMiddlewares }
+ } = useRuntimeConfig()
+ if (!parallelMiddlewares) {
+ return middleware(...args)
+ }
+
+ const { middlewares } = useMiddlewareParallelizationState()
+ middlewares.push(async () => app.runWithContext(() => middleware(...args)))
+ }
+}
+
+/**
+ * defineParallelizedNuxtRouteMiddleware() w/ parallelization support
+ */
+export const defineParallelizedNuxtRouteMiddleware = (
+ middleware: RouteMiddleware
+): RouteMiddleware => {
+ return withParallelization(middleware)
+}
+
+export const useFinalizeParallelMiddlewares = () => {
+ const state = useMiddlewareParallelizationState()
+ const logger = useLogger()
+
+ return {
+ finalize: async () => {
+ const middlewares = state.middlewares
+ if (!middlewares.length) {
+ return
+ }
+
+ logger.debug('Finalizing {count} parallel middlewares', {
+ count: middlewares.length,
+ middlewares
+ })
+
+ try {
+ const results = await Promise.all(middlewares.map((m) => m()))
+
+ // Report results
+ for (const resultItem of results) {
+ if (!isUndefinedOrVoid(resultItem) && resultItem !== true) {
+ return resultItem
+ }
+ }
+ } finally {
+ state.middlewares.length = 0
+ }
+ }
+ }
+}
diff --git a/packages/frontend-2/middleware/001-fe2-header.global.ts b/packages/frontend-2/middleware/001-fe2-header.global.ts
index d6bacc647..85b9d0d68 100644
--- a/packages/frontend-2/middleware/001-fe2-header.global.ts
+++ b/packages/frontend-2/middleware/001-fe2-header.global.ts
@@ -1,4 +1,4 @@
-export default defineNuxtRouteMiddleware(() => {
+export default defineParallelizedNuxtRouteMiddleware(() => {
// Add response header that shows this is a FE2 request
const { ssrContext } = useNuxtApp()
if (ssrContext) {
diff --git a/packages/frontend-2/middleware/002-redirects.global.ts b/packages/frontend-2/middleware/002-redirects.global.ts
index 7d256f29f..834047e73 100644
--- a/packages/frontend-2/middleware/002-redirects.global.ts
+++ b/packages/frontend-2/middleware/002-redirects.global.ts
@@ -67,7 +67,7 @@ const adminPageRgx = /^\/admin\/?/
* Setting up all kinds of redirects (e.g. for FE1 backwards compatibility)
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const logger = useLogger()
const path = to.path
const apollo = useApolloClientFromNuxt()
diff --git a/packages/frontend-2/middleware/003-acceptInvites.global.ts b/packages/frontend-2/middleware/003-acceptInvites.global.ts
index 4baa0ef1a..79c0c9ea0 100644
--- a/packages/frontend-2/middleware/003-acceptInvites.global.ts
+++ b/packages/frontend-2/middleware/003-acceptInvites.global.ts
@@ -23,7 +23,7 @@ const autoAcceptableWorkspaceInviteQuery = graphql(`
/**
* Handles all of the invite auto-accepting logic (when clicking on email accept links)
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const shouldTryProjectAccept = to.path.startsWith('/projects/')
diff --git a/packages/frontend-2/middleware/004-onboarding.global.ts b/packages/frontend-2/middleware/004-onboarding.global.ts
index d14b5c066..5a01ea020 100644
--- a/packages/frontend-2/middleware/004-onboarding.global.ts
+++ b/packages/frontend-2/middleware/004-onboarding.global.ts
@@ -19,16 +19,21 @@ import { convertThrowIntoFetchResult } from '~~/lib/common/helpers/graphql'
import { buildActiveUserWorkspaceExistenceCheckQuery } from '~/lib/workspaces/helpers/middleware'
import { useMiddlewareQueryFetchPolicy } from '~/lib/core/composables/navigation'
-export default defineNuxtRouteMiddleware(async (to, from) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to, from) => {
const isAuthPage = to.path.startsWith('/authn/')
const isSSOPath = to.path.includes('/sso/')
if (isAuthPage || isSSOPath) return
const client = useApolloClientFromNuxt()
const fetchPolicy = useMiddlewareQueryFetchPolicy()
+ const isWorkspacesEnabled = useIsWorkspacesEnabled()
// Fetch required data
- const [{ data: serverInfoData }, { data: userData }] = await Promise.all([
+ const [
+ { data: serverInfoData },
+ { data: userData },
+ { data: workspaceExistenceData }
+ ] = await Promise.all([
client
.query({
query: mainServerInfoDataQuery
@@ -39,7 +44,17 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
query: activeUserQuery,
fetchPolicy: fetchPolicy(to, from)
})
- .catch(convertThrowIntoFetchResult)
+ .catch(convertThrowIntoFetchResult),
+ ...(isWorkspacesEnabled.value
+ ? [
+ client
+ .query({
+ ...buildActiveUserWorkspaceExistenceCheckQuery(),
+ fetchPolicy: fetchPolicy(to, from)
+ })
+ .catch(convertThrowIntoFetchResult)
+ ]
+ : [{ data: undefined }])
])
// If user is not logged in, skip all checks
@@ -81,17 +96,9 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
// 3. Workspace join/create redirect
// Everything past this point is only relevant for workspace enabled instances
- const isWorkspacesEnabled = useIsWorkspacesEnabled()
if (!isWorkspacesEnabled.value) return
- const { data: workspaceExistenceData } = await client
- .query({
- ...buildActiveUserWorkspaceExistenceCheckQuery(),
- fetchPolicy: fetchPolicy(to, from)
- })
- .catch(convertThrowIntoFetchResult)
-
const workspaces = workspaceExistenceData?.activeUser?.workspaces?.items ?? []
const hasWorkspaces = workspaces.length > 0
const hasDiscoverableWorkspaces =
diff --git a/packages/frontend-2/middleware/999-parallelFinalize.ts b/packages/frontend-2/middleware/999-parallelFinalize.ts
new file mode 100644
index 000000000..f7b1ae013
--- /dev/null
+++ b/packages/frontend-2/middleware/999-parallelFinalize.ts
@@ -0,0 +1,9 @@
+import { useFinalizeParallelMiddlewares } from '~/lib/core/helpers/middleware'
+
+/**
+ * Should be the very last middleware that's run on ALL pages and navigations
+ */
+export default defineNuxtRouteMiddleware(async () => {
+ const { finalize } = useFinalizeParallelMiddlewares()
+ return await finalize()
+})
diff --git a/packages/frontend-2/middleware/admin.ts b/packages/frontend-2/middleware/admin.ts
index 20b0cfb0f..55dc822d9 100644
--- a/packages/frontend-2/middleware/admin.ts
+++ b/packages/frontend-2/middleware/admin.ts
@@ -6,7 +6,7 @@ import { Roles } from '@speckle/shared'
/**
* Apply this to a page to prevent access by non-admin users
*/
-export default defineNuxtRouteMiddleware(async () => {
+export default defineParallelizedNuxtRouteMiddleware(async () => {
const client = useApolloClientFromNuxt()
const { data } = await client
diff --git a/packages/frontend-2/middleware/auth.ts b/packages/frontend-2/middleware/auth.ts
index a0fc2488d..c239d0626 100644
--- a/packages/frontend-2/middleware/auth.ts
+++ b/packages/frontend-2/middleware/auth.ts
@@ -7,7 +7,7 @@ import { loginRoute } from '~~/lib/common/helpers/route'
/**
* Apply this to a page to prevent unauthenticated access
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const nuxt = useNuxtApp()
const client = useApolloClientFromNuxt()
const postAuthRedirect = usePostAuthRedirect({ route: to })
diff --git a/packages/frontend-2/middleware/canViewProjectTokens.ts b/packages/frontend-2/middleware/canViewProjectTokens.ts
index 98b084f37..c045b8077 100644
--- a/packages/frontend-2/middleware/canViewProjectTokens.ts
+++ b/packages/frontend-2/middleware/canViewProjectTokens.ts
@@ -19,7 +19,7 @@ const canViewProjectTokensQuery = graphql(`
/**
* Apply this to a page to prevent unauthenticated access to tokens and ensure the user is the owner
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const client = useApolloClientFromNuxt()
const projectId = to.params.id as string
diff --git a/packages/frontend-2/middleware/canViewSettings.ts b/packages/frontend-2/middleware/canViewSettings.ts
index 5707a92d4..596897d12 100644
--- a/packages/frontend-2/middleware/canViewSettings.ts
+++ b/packages/frontend-2/middleware/canViewSettings.ts
@@ -19,7 +19,7 @@ const canViewProjectSettingsQuery = graphql(`
/**
* Apply this to a page to prevent unauthenticated access to settings ensuring the user is a collaborator
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const client = useApolloClientFromNuxt()
// Fetch project role data to check if the user is a collaborator
diff --git a/packages/frontend-2/middleware/canViewWebhooks.ts b/packages/frontend-2/middleware/canViewWebhooks.ts
index 130bffa33..3cca1e7d1 100644
--- a/packages/frontend-2/middleware/canViewWebhooks.ts
+++ b/packages/frontend-2/middleware/canViewWebhooks.ts
@@ -19,7 +19,7 @@ const canViewProjectWebhooksQuery = graphql(`
/**
* Apply this to a page to prevent unauthenticated access to webhooks and ensure the user is the owner
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const client = useApolloClientFromNuxt()
// Fetch project role data to check if the user is the owner
diff --git a/packages/frontend-2/middleware/dashboardRedirect.ts b/packages/frontend-2/middleware/dashboardRedirect.ts
index 970a069fd..d20972129 100644
--- a/packages/frontend-2/middleware/dashboardRedirect.ts
+++ b/packages/frontend-2/middleware/dashboardRedirect.ts
@@ -2,7 +2,7 @@ import { projectsRoute, workspaceRoute } from '~/lib/common/helpers/route'
import { useApolloClientFromNuxt } from '~~/lib/common/composables/graphql'
import { activeUserActiveWorkspaceCheckQuery } from '~/lib/auth/graphql/queries'
-export default defineNuxtRouteMiddleware(async () => {
+export default defineParallelizedNuxtRouteMiddleware(async () => {
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const client = useApolloClientFromNuxt()
diff --git a/packages/frontend-2/middleware/guest.ts b/packages/frontend-2/middleware/guest.ts
index b4018bb30..7cdbc44f0 100644
--- a/packages/frontend-2/middleware/guest.ts
+++ b/packages/frontend-2/middleware/guest.ts
@@ -8,7 +8,7 @@ const exclusionList = ['authorize-app', 'reset-password']
/**
* Apply this to a page to prevent authenticated access
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const nuxt = useNuxtApp()
const client = useApolloClientFromNuxt()
diff --git a/packages/frontend-2/middleware/headers.global.ts b/packages/frontend-2/middleware/headers.global.ts
index 19d6a4327..d9ba822c9 100644
--- a/packages/frontend-2/middleware/headers.global.ts
+++ b/packages/frontend-2/middleware/headers.global.ts
@@ -1,4 +1,4 @@
-export default defineNuxtRouteMiddleware((to) => {
+export default defineParallelizedNuxtRouteMiddleware((to) => {
const { ssrContext } = useNuxtApp()
if (ssrContext) {
diff --git a/packages/frontend-2/middleware/projectsActiveCheck.ts b/packages/frontend-2/middleware/projectsActiveCheck.ts
index 1375b27c2..30c0aedf7 100644
--- a/packages/frontend-2/middleware/projectsActiveCheck.ts
+++ b/packages/frontend-2/middleware/projectsActiveCheck.ts
@@ -3,7 +3,7 @@ import { useSetActiveWorkspace } from '~/lib/user/composables/activeWorkspace'
/**
* Clear active workspace when navigating to the projects page
*/
-export default defineNuxtRouteMiddleware(async () => {
+export default defineParallelizedNuxtRouteMiddleware(async () => {
const { setActiveWorkspace } = useSetActiveWorkspace()
const { isLoggedIn } = useActiveUser()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
diff --git a/packages/frontend-2/middleware/requireDiscoverableWorkspaces.ts b/packages/frontend-2/middleware/requireDiscoverableWorkspaces.ts
index b95265460..f2c815ef2 100644
--- a/packages/frontend-2/middleware/requireDiscoverableWorkspaces.ts
+++ b/packages/frontend-2/middleware/requireDiscoverableWorkspaces.ts
@@ -6,7 +6,7 @@ import { homeRoute, workspaceCreateRoute } from '~~/lib/common/helpers/route'
/**
* Redirect user to /workspaces/actions/create, if they have no discoverable workspaces
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const isWorkspacesEnabled = useIsWorkspacesEnabled()
if (!isWorkspacesEnabled.value) return
diff --git a/packages/frontend-2/middleware/requireSsoEnabled.ts b/packages/frontend-2/middleware/requireSsoEnabled.ts
index fc73c79f4..9ee47a240 100644
--- a/packages/frontend-2/middleware/requireSsoEnabled.ts
+++ b/packages/frontend-2/middleware/requireSsoEnabled.ts
@@ -5,7 +5,7 @@ import { useWorkspacePublicSsoCheck } from '~/lib/workspaces/composables/sso'
/**
* Used to validate that the workspace has SSO enabled, redirects to workspace page if not
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
// Skip middleware when handling SSO callback with access code.
// This page serves as both the SSO login page and OAuth callback URL.
// We need to let the callback through to process the access code before any redirects.
diff --git a/packages/frontend-2/middleware/requireValidAutomation.ts b/packages/frontend-2/middleware/requireValidAutomation.ts
index ec3beb931..82235b7dd 100644
--- a/packages/frontend-2/middleware/requireValidAutomation.ts
+++ b/packages/frontend-2/middleware/requireValidAutomation.ts
@@ -7,7 +7,7 @@ import {
} from '~/lib/common/helpers/graphql'
import { projectAutomationAccessCheckQuery } from '~/lib/projects/graphql/queries'
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const projectId = to.params.id as string
// const automationId = to.params.aid as string
diff --git a/packages/frontend-2/middleware/requireValidFunction.ts b/packages/frontend-2/middleware/requireValidFunction.ts
index 3675694ec..d2bea23f5 100644
--- a/packages/frontend-2/middleware/requireValidFunction.ts
+++ b/packages/frontend-2/middleware/requireValidFunction.ts
@@ -5,7 +5,7 @@ import {
getFirstErrorMessage
} from '~/lib/common/helpers/graphql'
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const functionId = to.params.fid as string
const isAutomateEnabled = useIsAutomateModuleEnabled()
diff --git a/packages/frontend-2/middleware/requireValidModel.ts b/packages/frontend-2/middleware/requireValidModel.ts
index 47b57c12d..65697a119 100644
--- a/packages/frontend-2/middleware/requireValidModel.ts
+++ b/packages/frontend-2/middleware/requireValidModel.ts
@@ -1,3 +1,4 @@
+import { useMiddlewareQueryFetchPolicy } from '~/lib/core/composables/navigation'
import {
castToSupportedVisibility,
SupportedProjectVisibility
@@ -13,16 +14,18 @@ import { projectModelCheckQuery } from '~~/lib/projects/graphql/queries'
/**
* Used in project page to validate that project ID refers to a valid project and redirects to 404 if not
*/
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to, from) => {
const projectId = to.params.id as string
const modelId = to.params.modelId as string
const client = useApolloClientFromNuxt()
+ const fetchPolicy = useMiddlewareQueryFetchPolicy()
const { data, errors } = await client
.query({
query: projectModelCheckQuery,
- variables: { projectId, modelId }
+ variables: { projectId, modelId },
+ fetchPolicy: fetchPolicy(to, from)
})
.catch(convertThrowIntoFetchResult)
diff --git a/packages/frontend-2/middleware/requireValidProject.ts b/packages/frontend-2/middleware/requireValidProject.ts
index b2f4db147..29b11ba1e 100644
--- a/packages/frontend-2/middleware/requireValidProject.ts
+++ b/packages/frontend-2/middleware/requireValidProject.ts
@@ -13,7 +13,7 @@ import { useMiddlewareQueryFetchPolicy } from '~/lib/core/composables/navigation
/**
* Used in project page to validate that project ID refers to a valid project and redirects to 404 if not
*/
-export default defineNuxtRouteMiddleware(async (to, from) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to, from) => {
const projectId = to.params.id as string
// Check if embed token is present in URL
diff --git a/packages/frontend-2/middleware/requireValidWorkspace.ts b/packages/frontend-2/middleware/requireValidWorkspace.ts
index c021b73ac..8239dc3cf 100644
--- a/packages/frontend-2/middleware/requireValidWorkspace.ts
+++ b/packages/frontend-2/middleware/requireValidWorkspace.ts
@@ -10,7 +10,7 @@ import { useMiddlewareQueryFetchPolicy } from '~/lib/core/composables/navigation
/**
* Used to validate that the workspace ID refers to a valid workspace and redirects to 404 if not
*/
-export default defineNuxtRouteMiddleware(async (to, from) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to, from) => {
const workspaceSlug = to.params.slug as string
const client = useApolloClientFromNuxt()
diff --git a/packages/frontend-2/middleware/requiresAutomateEnabled.ts b/packages/frontend-2/middleware/requiresAutomateEnabled.ts
index 415ad63e8..36499160a 100644
--- a/packages/frontend-2/middleware/requiresAutomateEnabled.ts
+++ b/packages/frontend-2/middleware/requiresAutomateEnabled.ts
@@ -1,4 +1,4 @@
-export default defineNuxtRouteMiddleware(() => {
+export default defineParallelizedNuxtRouteMiddleware(() => {
const isAutomateEnabled = useIsAutomateModuleEnabled()
if (!isAutomateEnabled.value) {
return abortNavigation(
diff --git a/packages/frontend-2/middleware/requiresWorkspacesEnabled.ts b/packages/frontend-2/middleware/requiresWorkspacesEnabled.ts
index 5d7098ca7..5c944b0fb 100644
--- a/packages/frontend-2/middleware/requiresWorkspacesEnabled.ts
+++ b/packages/frontend-2/middleware/requiresWorkspacesEnabled.ts
@@ -1,4 +1,4 @@
-export default defineNuxtRouteMiddleware(() => {
+export default defineParallelizedNuxtRouteMiddleware(() => {
const isWorkspacesEnabled = useIsWorkspacesEnabled()
// If workspaces are enabled, continue as normal
diff --git a/packages/frontend-2/middleware/settings.ts b/packages/frontend-2/middleware/settings.ts
index d4ed6be9d..e0a8f4e5c 100644
--- a/packages/frontend-2/middleware/settings.ts
+++ b/packages/frontend-2/middleware/settings.ts
@@ -1,6 +1,6 @@
import { useSettingsMenuState } from '~/lib/settings/composables/menu'
-export default defineNuxtRouteMiddleware((to, from) => {
+export default defineParallelizedNuxtRouteMiddleware((to, from) => {
const settingsMenuState = useSettingsMenuState()
if (to.path.startsWith('/settings') && !from.path.startsWith('/settings')) {
diff --git a/packages/frontend-2/middleware/thread.ts b/packages/frontend-2/middleware/thread.ts
index 3b37eacf4..e84d8695b 100644
--- a/packages/frontend-2/middleware/thread.ts
+++ b/packages/frontend-2/middleware/thread.ts
@@ -14,7 +14,7 @@ const resolveLinkQuery = graphql(`
}
`)
-export default defineNuxtRouteMiddleware(async (to) => {
+export default defineParallelizedNuxtRouteMiddleware(async (to) => {
const client = useApolloClientFromNuxt()
const threadId = to.params.threadId as string
const projectId = to.params.id as string
diff --git a/packages/frontend-2/nuxt.config.ts b/packages/frontend-2/nuxt.config.ts
index 71d06fffd..df1d7d1bc 100644
--- a/packages/frontend-2/nuxt.config.ts
+++ b/packages/frontend-2/nuxt.config.ts
@@ -83,12 +83,14 @@ export default defineNuxtConfig({
datadogSite: '',
datadogService: '',
datadogEnv: '',
- intercomAppId: ''
+ intercomAppId: '',
+ parallelMiddlewares: true
}
},
experimental: {
- emitRouteChunkError: 'automatic-immediate'
+ emitRouteChunkError: 'automatic-immediate',
+ asyncContext: true // necessary for parallel middlewares
},
alias: {
@@ -171,7 +173,11 @@ export default defineNuxtConfig({
headers: {
// No search engine indexing on any of the pages anywhere! TODO: Come up with a more appropriate policy
'X-Robots-Tag': 'noindex, nofollow, noarchive'
- }
+ },
+ appMiddleware: [
+ // Has to be applied to all pages and as the very last app middleware (hence the 999 prefix)
+ '999-parallel-finalize'
+ ]
},
'/functions': {
redirect: {
diff --git a/packages/frontend-2/utils/globals.ts b/packages/frontend-2/utils/globals.ts
index 6b71b1c15..5365c80b5 100644
--- a/packages/frontend-2/utils/globals.ts
+++ b/packages/frontend-2/utils/globals.ts
@@ -14,6 +14,7 @@ import {
} from '~/lib/common/helpers/graphql'
import { checkIfIsInPlaceNavigation } from '~/lib/common/helpers/navigation'
import { ViewerEventBusKeys } from '~/lib/viewer/helpers/eventBus'
+import { defineParallelizedNuxtRouteMiddleware } from '~/lib/core/helpers/middleware'
/**
* Debugging helper to ensure variables are available in debugging scope
@@ -40,5 +41,6 @@ export {
ROOT_QUERY,
ROOT_MUTATION,
ROOT_SUBSCRIPTION,
- ViewerEventBusKeys
+ ViewerEventBusKeys,
+ defineParallelizedNuxtRouteMiddleware
}