fix(nuxt): use payload url for isPrerendered, not current route (#24031)

This commit is contained in:
Daniel Roe 2023-10-30 21:56:34 +01:00 committed by GitHub
parent e297368ee3
commit 62b7917d2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 51 deletions

View File

@ -23,7 +23,7 @@ export function loadPayload (url: string, opts: LoadPayloadOptions = {}): Record
if (payloadURL in cache) { if (payloadURL in cache) {
return cache[payloadURL] return cache[payloadURL]
} }
cache[payloadURL] = isPrerendered().then((prerendered) => { cache[payloadURL] = isPrerendered(url).then((prerendered) => {
if (!prerendered) { if (!prerendered) {
cache[payloadURL] = null cache[payloadURL] = null
return null return null
@ -78,11 +78,7 @@ async function _importPayload (payloadURL: string) {
export async function isPrerendered (url = useRoute().path) { export async function isPrerendered (url = useRoute().path) {
// Note: Alternative for server is checking x-nitro-prerender header // Note: Alternative for server is checking x-nitro-prerender header
const nuxtApp = useNuxtApp() if (!appManifest) { return !!useNuxtApp().payload.prerenderedAt }
if (nuxtApp.payload.prerenderedAt) {
return true
}
if (!appManifest) { return false }
const manifest = await getAppManifest() const manifest = await getAppManifest()
if (manifest.prerendered.includes(url)) { if (manifest.prerendered.includes(url)) {
return true return true

View File

@ -244,53 +244,55 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
} }
) )
nuxt.hook('nitro:build:before', async (nitro) => { nuxt.hook('nitro:init', (nitro) => {
const routeRules = {} as Record<string, any> nitro.hooks.hook('rollup:before', async (nitro) => {
const _routeRules = nitro.options.routeRules const routeRules = {} as Record<string, any>
for (const key in _routeRules) { const _routeRules = nitro.options.routeRules
if (key === '/__nuxt_error') { continue } for (const key in _routeRules) {
const filteredRules = Object.entries(_routeRules[key]) if (key === '/__nuxt_error') { continue }
.filter(([key, value]) => ['prerender', 'redirect'].includes(key) && value) const filteredRules = Object.entries(_routeRules[key])
.map(([key, value]: any) => { .filter(([key, value]) => ['prerender', 'redirect'].includes(key) && value)
if (key === 'redirect') { .map(([key, value]: any) => {
return [key, typeof value === 'string' ? value : value.to] if (key === 'redirect') {
} return [key, typeof value === 'string' ? value : value.to]
return [key, value] }
}) return [key, value]
if (filteredRules.length > 0) { })
routeRules[key] = Object.fromEntries(filteredRules) if (filteredRules.length > 0) {
} routeRules[key] = Object.fromEntries(filteredRules)
}
// Add pages prerendered but not covered by route rules
const prerenderedRoutes = new Set<string>()
const routeRulesMatcher = toRouteMatcher(
createRadixRouter({ routes: routeRules })
)
const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js'
for (const route of nitro._prerenderedRoutes || []) {
if (!route.error && route.route.endsWith(payloadSuffix)) {
const url = route.route.slice(0, -payloadSuffix.length) || '/'
const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record<string, any>
if (!rules.prerender) {
prerenderedRoutes.add(url)
} }
} }
}
const manifest = { // Add pages prerendered but not covered by route rules
id: buildId, const prerenderedRoutes = new Set<string>()
timestamp: buildTimestamp, const routeRulesMatcher = toRouteMatcher(
matcher: exportMatcher(routeRulesMatcher), createRadixRouter({ routes: routeRules })
prerendered: nuxt.options.dev ? [] : [...prerenderedRoutes] )
} const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js'
for (const route of nitro._prerenderedRoutes || []) {
if (!route.error && route.route.endsWith(payloadSuffix)) {
const url = route.route.slice(0, -payloadSuffix.length) || '/'
const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record<string, any>
if (!rules.prerender) {
prerenderedRoutes.add(url)
}
}
}
await fsp.mkdir(join(tempDir, 'meta'), { recursive: true }) const manifest = {
await fsp.writeFile(join(tempDir, 'latest.json'), JSON.stringify({ id: buildId,
id: buildId, timestamp: buildTimestamp,
timestamp: buildTimestamp matcher: exportMatcher(routeRulesMatcher),
})) prerendered: nuxt.options.dev ? [] : [...prerenderedRoutes]
await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest)) }
await fsp.mkdir(join(tempDir, 'meta'), { recursive: true })
await fsp.writeFile(join(tempDir, 'latest.json'), JSON.stringify({
id: buildId,
timestamp: buildTimestamp
}))
await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest))
})
}) })
} }
@ -457,6 +459,14 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
}) })
} }
// Copy public assets after prerender so app manifest can be present
if (!nuxt.options.dev) {
nitro.hooks.hook('rollup:before', async (nitro) => {
await copyPublicAssets(nitro)
await nuxt.callHook('nitro:build:public-assets', nitro)
})
}
// nuxt build/dev // nuxt build/dev
nuxt.hook('build:done', async () => { nuxt.hook('build:done', async () => {
await nuxt.callHook('nitro:build:before', nitro) await nuxt.callHook('nitro:build:before', nitro)
@ -464,8 +474,6 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
await build(nitro) await build(nitro)
} else { } else {
await prepare(nitro) await prepare(nitro)
await copyPublicAssets(nitro)
await nuxt.callHook('nitro:build:public-assets', nitro)
await prerender(nitro) await prerender(nitro)
logger.restoreAll() logger.restoreAll()