Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

feat(nuxt): prefetch middleware/layouts + await layout loading #10155

Merged
merged 4 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/nuxt/src/pages/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,11 @@ export default defineNuxtModule({
addVitePlugin(PageMetaPlugin.vite(pageMetaOptions))
addWebpackPlugin(PageMetaPlugin.webpack(pageMetaOptions))

// Add prefetching support for middleware & layouts
addPlugin(resolve(runtimeDir, 'plugins/prefetch.client'))

// Add router plugin
addPlugin(resolve(runtimeDir, 'router'))
addPlugin(resolve(runtimeDir, 'plugins/router'))

const getSources = (pages: NuxtPage[]): string[] => pages.flatMap(p =>
[relative(nuxt.options.srcDir, p.file), ...getSources(p.children || [])]
Expand Down
40 changes: 40 additions & 0 deletions packages/nuxt/src/pages/runtime/plugins/prefetch.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { hasProtocol } from 'ufo'
import { defineNuxtPlugin, useNuxtApp, useRouter } from '#app'
// @ts-ignore
import layouts from '#build/layouts'
// @ts-ignore
import { namedMiddleware } from '#build/middleware'

export default defineNuxtPlugin(() => {
const nuxtApp = useNuxtApp()
const router = useRouter()

// Force layout prefetch on route changes
nuxtApp.hooks.hook('app:mounted', () => {
router.beforeEach(async (to) => {
const layout = to?.meta?.layout
if (layout && typeof layouts[layout] === 'function') {
await layouts[layout]()
}
})
})
// Prefetch layouts & middleware
nuxtApp.hooks.hook('link:prefetch', (url) => {
if (hasProtocol(url)) { return }
const route = router.resolve(url)
if (!route) { return }
const layout = route?.meta?.layout
let middleware = Array.isArray(route?.meta?.middleware) ? route?.meta?.middleware : [route?.meta?.middleware]
middleware = middleware.filter(m => typeof m === 'string')

for (const name of middleware) {
if (typeof namedMiddleware[name] === 'function') {
namedMiddleware[name]()
}
}

if (layout && typeof layouts[layout] === 'function') {
layouts[layout]()
}
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from 'vue-router'
import { createError } from 'h3'
import { withoutBase, isEqual } from 'ufo'
import type NuxtPage from './page'
import type NuxtPage from '../page'
import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, showError, clearError, navigateTo, useError, useState } from '#app'
// @ts-ignore
import _routes from '#build/routes'
Expand Down