mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-28 08:32:06 +00:00
feat(nuxt): experimental extraPageMetaExtractionKeys
(#30015)
This commit is contained in:
parent
0f3e1e9442
commit
16ef9be903
@ -395,6 +395,35 @@ In addition, any changes to files within `srcDir` will trigger a rebuild of the
|
||||
A maximum of 10 cache tarballs are kept.
|
||||
::
|
||||
|
||||
## extraPageMetaExtractionKeys
|
||||
|
||||
The `definePageMeta()` macro is a useful way to collect build-time meta about pages. Nuxt itself provides a set list of supported keys which is used to power some of the internal features such as redirects, page aliases and custom paths.
|
||||
|
||||
This option allows passing additional keys to extract from the page metadata when using `scanPageMeta`.
|
||||
|
||||
```vue
|
||||
<script lang="ts" setup>
|
||||
definePageMeta({
|
||||
foo: 'bar'
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
```ts
|
||||
export default defineNuxtConfig({
|
||||
experimental: {
|
||||
extraPageMetaExtractionKeys: ['foo'],
|
||||
},
|
||||
hooks: {
|
||||
'pages:resolved' (ctx) {
|
||||
// ✅ foo is available
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
This allows modules to access additional metadata from the page metadata in the build context. If you are using this within a module, it's recommended also to [augment the `NuxtPage` types with your keys](/docs/guide/directory-structure/pages#typing-custom-metadata).
|
||||
|
||||
## normalizeComponentNames
|
||||
|
||||
Ensure that auto-generated Vue component names match the full component name
|
||||
|
@ -71,13 +71,14 @@ export async function resolvePagesRoutes (): Promise<NuxtPage[]> {
|
||||
return pages
|
||||
}
|
||||
|
||||
const augmentCtx = { extraExtractionKeys: nuxt.options.experimental.extraPageMetaExtractionKeys }
|
||||
if (shouldAugment === 'after-resolve') {
|
||||
await nuxt.callHook('pages:extend', pages)
|
||||
await augmentPages(pages, nuxt.vfs)
|
||||
await augmentPages(pages, nuxt.vfs, augmentCtx)
|
||||
} else {
|
||||
const augmentedPages = await augmentPages(pages, nuxt.vfs)
|
||||
const augmentedPages = await augmentPages(pages, nuxt.vfs, augmentCtx)
|
||||
await nuxt.callHook('pages:extend', pages)
|
||||
await augmentPages(pages, nuxt.vfs, { pagesToSkip: augmentedPages })
|
||||
await augmentPages(pages, nuxt.vfs, { pagesToSkip: augmentedPages, ...augmentCtx })
|
||||
augmentedPages?.clear()
|
||||
}
|
||||
|
||||
@ -158,13 +159,15 @@ export function generateRoutesFromFiles (files: ScannedFile[], options: Generate
|
||||
interface AugmentPagesContext {
|
||||
pagesToSkip?: Set<string>
|
||||
augmentedPages?: Set<string>
|
||||
extraExtractionKeys?: string[]
|
||||
}
|
||||
|
||||
export async function augmentPages (routes: NuxtPage[], vfs: Record<string, string>, ctx: AugmentPagesContext = {}) {
|
||||
ctx.augmentedPages ??= new Set()
|
||||
for (const route of routes) {
|
||||
if (route.file && !ctx.pagesToSkip?.has(route.file)) {
|
||||
const fileContent = route.file in vfs ? vfs[route.file]! : fs.readFileSync(await resolvePath(route.file), 'utf-8')
|
||||
const routeMeta = await getRouteMeta(fileContent, route.file)
|
||||
const routeMeta = await getRouteMeta(fileContent, route.file, ctx.extraExtractionKeys)
|
||||
if (route.meta) {
|
||||
routeMeta.meta = { ...routeMeta.meta, ...route.meta }
|
||||
}
|
||||
@ -196,12 +199,12 @@ export function extractScriptContent (html: string) {
|
||||
}
|
||||
|
||||
const PAGE_META_RE = /definePageMeta\([\s\S]*?\)/
|
||||
const extractionKeys = ['name', 'path', 'props', 'alias', 'redirect'] as const
|
||||
const defaultExtractionKeys = ['name', 'path', 'props', 'alias', 'redirect'] as const
|
||||
const DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const
|
||||
|
||||
const pageContentsCache: Record<string, string> = {}
|
||||
const metaCache: Record<string, Partial<Record<keyof NuxtPage, any>>> = {}
|
||||
export async function getRouteMeta (contents: string, absolutePath: string): Promise<Partial<Record<keyof NuxtPage, any>>> {
|
||||
export async function getRouteMeta (contents: string, absolutePath: string, extraExtractionKeys: string[] = []): Promise<Partial<Record<keyof NuxtPage, any>>> {
|
||||
// set/update pageContentsCache, invalidate metaCache on cache mismatch
|
||||
if (!(absolutePath in pageContentsCache) || pageContentsCache[absolutePath] !== contents) {
|
||||
pageContentsCache[absolutePath] = contents
|
||||
@ -221,6 +224,8 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
||||
|
||||
const extractedMeta = {} as Partial<Record<keyof NuxtPage, any>>
|
||||
|
||||
const extractionKeys = new Set<keyof NuxtPage>([...defaultExtractionKeys, ...extraExtractionKeys as Array<keyof NuxtPage>])
|
||||
|
||||
for (const script of scriptBlocks) {
|
||||
if (!PAGE_META_RE.test(script.code)) {
|
||||
continue
|
||||
@ -295,7 +300,7 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
||||
continue
|
||||
}
|
||||
const name = property.key.type === 'Identifier' ? property.key.name : String(property.value)
|
||||
if (!(extractionKeys as unknown as string[]).includes(name)) {
|
||||
if (!extractionKeys.has(name as keyof NuxtPage)) {
|
||||
dynamicProperties.add('meta')
|
||||
break
|
||||
}
|
||||
|
@ -142,6 +142,24 @@ describe('page metadata', () => {
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
it('should extract configured extra meta', async () => {
|
||||
const meta = await getRouteMeta(`
|
||||
<script setup>
|
||||
definePageMeta({
|
||||
foo: 'bar',
|
||||
bar: true,
|
||||
})
|
||||
</script>
|
||||
`, filePath, ['bar', 'foo'])
|
||||
|
||||
expect(meta).toMatchInlineSnapshot(`
|
||||
{
|
||||
"bar": true,
|
||||
"foo": "bar",
|
||||
}
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('normalizeRoutes', () => {
|
||||
|
@ -308,6 +308,16 @@ export default defineUntypedSchema({
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Configure additional keys to extract from the page metadata when using `scanPageMeta`.
|
||||
*
|
||||
* This allows modules to access additional metadata from the page metadata. It's recommended
|
||||
* to augment the NuxtPage types with your keys.
|
||||
*
|
||||
* @type {string[]}
|
||||
*/
|
||||
extraPageMetaExtractionKeys: [],
|
||||
|
||||
/**
|
||||
* Automatically share payload _data_ between pages that are prerendered. This can result in a significant
|
||||
* performance improvement when prerendering sites that use `useAsyncData` or `useFetch` and fetch the same
|
||||
|
Loading…
Reference in New Issue
Block a user