From 0536dbeed9d77e9d4840fc0dcf84df9166c3c615 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 10 Jun 2024 17:24:43 +0100 Subject: [PATCH] fix(nuxt): also augment page metadata after `pages:extend` hook (#27134) --- .../1.experimental-features.md | 4 +- packages/nuxt/src/pages/module.ts | 16 ++++---- packages/nuxt/src/pages/utils.ts | 40 ++++++++++++++----- packages/nuxt/test/pages.test.ts | 7 ++-- packages/schema/src/config/experimental.ts | 2 +- 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/docs/2.guide/3.going-further/1.experimental-features.md b/docs/2.guide/3.going-further/1.experimental-features.md index 691a2187c3..9105b2ebfa 100644 --- a/docs/2.guide/3.going-further/1.experimental-features.md +++ b/docs/2.guide/3.going-further/1.experimental-features.md @@ -386,7 +386,7 @@ This option allows exposing some route metadata defined in `definePageMeta` at b This only works with static or strings/arrays rather than variables or conditional assignment. See [original issue](https://github.com/nuxt/nuxt/issues/24770) for more information and context. - +``` ## cookieStore diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index ee5b8c1c79..ae80fd4e02 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -61,8 +61,12 @@ export default defineNuxtModule({ } const pages = await resolvePagesRoutes() - await nuxt.callHook('pages:extend', pages) - if (pages.length) { return true } + if (pages.length) { + if (nuxt.apps.default) { + nuxt.apps.default.pages = pages + } + return true + } return false } @@ -75,7 +79,6 @@ export default defineNuxtModule({ nuxt.hook('app:templates', async (app) => { app.pages = await resolvePagesRoutes() - await nuxt.callHook('pages:extend', app.pages) if (!nuxt.options.ssr && app.pages.some(p => p.mode === 'server')) { logger.warn('Using server pages with `ssr: false` is not supported with auto-detected component islands. Set `experimental.componentIslands` to `true`.') @@ -153,10 +156,9 @@ export default defineNuxtModule({ logs: nuxt.options.debug, async beforeWriteFiles (rootPage) { rootPage.children.forEach(child => child.delete()) - let pages = nuxt.apps.default?.pages - if (!pages) { - pages = await resolvePagesRoutes() - await nuxt.callHook('pages:extend', pages) + const pages = nuxt.apps.default?.pages || await resolvePagesRoutes() + if (nuxt.apps.default) { + nuxt.apps.default.pages = pages } function addPage (parent: EditableTreeNode, page: NuxtPage) { // @ts-expect-error TODO: either fix types upstream or figure out another diff --git a/packages/nuxt/src/pages/utils.ts b/packages/nuxt/src/pages/utils.ts index 9bd65069fe..79e0321e93 100644 --- a/packages/nuxt/src/pages/utils.ts +++ b/packages/nuxt/src/pages/utils.ts @@ -58,21 +58,30 @@ export async function resolvePagesRoutes (): Promise { scannedFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath, 'en-US')) const allRoutes = await generateRoutesFromFiles(uniqueBy(scannedFiles, 'relativePath'), { - shouldExtractBuildMeta: nuxt.options.experimental.scanPageMeta || nuxt.options.experimental.typedPages, shouldUseServerComponents: !!nuxt.options.experimental.componentIslands, - vfs: nuxt.vfs, }) - return uniqueBy(allRoutes, 'path') + const pages = uniqueBy(allRoutes, 'path') + + const shouldAugment = nuxt.options.experimental.scanPageMeta || nuxt.options.experimental.typedPages + + if (shouldAugment) { + const augmentedPages = await augmentPages(pages, nuxt.vfs) + await nuxt.callHook('pages:extend', pages) + await augmentPages(pages, nuxt.vfs, augmentedPages) + augmentedPages.clear() + } else { + await nuxt.callHook('pages:extend', pages) + } + + return pages } type GenerateRoutesFromFilesOptions = { - shouldExtractBuildMeta?: boolean shouldUseServerComponents?: boolean - vfs?: Record } -export async function generateRoutesFromFiles (files: ScannedFile[], options: GenerateRoutesFromFilesOptions = {}): Promise { +export function generateRoutesFromFiles (files: ScannedFile[], options: GenerateRoutesFromFilesOptions = {}): NuxtPage[] { const routes: NuxtPage[] = [] for (const file of files) { @@ -124,17 +133,26 @@ export async function generateRoutesFromFiles (files: ScannedFile[], options: Ge } } - if (options.shouldExtractBuildMeta && options.vfs) { - const fileContent = file.absolutePath in options.vfs ? options.vfs[file.absolutePath] : fs.readFileSync(file.absolutePath, 'utf-8') - Object.assign(route, await getRouteMeta(fileContent, file.absolutePath)) - } - parent.push(route) } return prepareRoutes(routes) } +export async function augmentPages (routes: NuxtPage[], vfs: Record, augmentedPages = new Set()) { + for (const route of routes) { + if (!augmentedPages.has(route) && route.file) { + const fileContent = route.file in vfs ? vfs[route.file] : fs.readFileSync(route.file, 'utf-8') + Object.assign(route, await getRouteMeta(fileContent, route.file)) + } + + if (route.children && route.children.length > 0) { + await augmentPages(route.children, vfs) + } + } + return augmentedPages +} + const SFC_SCRIPT_RE = /]*>([\s\S]*?)<\/script[^>]*>/i export function extractScriptContent (html: string) { const match = html.match(SFC_SCRIPT_RE) diff --git a/packages/nuxt/test/pages.test.ts b/packages/nuxt/test/pages.test.ts index 36d996d635..3babb4cf11 100644 --- a/packages/nuxt/test/pages.test.ts +++ b/packages/nuxt/test/pages.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, vi } from 'vitest' import type { NuxtPage } from 'nuxt/schema' -import { generateRoutesFromFiles, normalizeRoutes, pathToNitroGlob } from '../src/pages/utils' +import { augmentPages, generateRoutesFromFiles, normalizeRoutes, pathToNitroGlob } from '../src/pages/utils' import { generateRouteKey } from '../src/pages/runtime/utils' describe('pages:generateRoutesFromFiles', () => { @@ -568,11 +568,12 @@ describe('pages:generateRoutesFromFiles', () => { ) as Record try { - result = await generateRoutesFromFiles(test.files.map(file => ({ + result = generateRoutesFromFiles(test.files.map(file => ({ shouldUseServerComponents: true, absolutePath: file.path, relativePath: file.path.replace(/^(pages|layer\/pages)\//, ''), - })), { shouldExtractBuildMeta: true, vfs }) + }))) + await augmentPages(result, vfs) } catch (error: any) { expect(error.message).toEqual(test.error) } diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index bf984023fc..b80f0beca1 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -378,7 +378,7 @@ export default defineUntypedSchema({ * * https://github.com/nuxt/nuxt/issues/24770 */ - scanPageMeta: false, + scanPageMeta: true, /** * Automatically share payload _data_ between pages that are prerendered. This can result in a significant