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.
|
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
|
## normalizeComponentNames
|
||||||
|
|
||||||
Ensure that auto-generated Vue component names match the full component name
|
Ensure that auto-generated Vue component names match the full component name
|
||||||
|
@ -71,13 +71,14 @@ export async function resolvePagesRoutes (): Promise<NuxtPage[]> {
|
|||||||
return pages
|
return pages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const augmentCtx = { extraExtractionKeys: nuxt.options.experimental.extraPageMetaExtractionKeys }
|
||||||
if (shouldAugment === 'after-resolve') {
|
if (shouldAugment === 'after-resolve') {
|
||||||
await nuxt.callHook('pages:extend', pages)
|
await nuxt.callHook('pages:extend', pages)
|
||||||
await augmentPages(pages, nuxt.vfs)
|
await augmentPages(pages, nuxt.vfs, augmentCtx)
|
||||||
} else {
|
} else {
|
||||||
const augmentedPages = await augmentPages(pages, nuxt.vfs)
|
const augmentedPages = await augmentPages(pages, nuxt.vfs, augmentCtx)
|
||||||
await nuxt.callHook('pages:extend', pages)
|
await nuxt.callHook('pages:extend', pages)
|
||||||
await augmentPages(pages, nuxt.vfs, { pagesToSkip: augmentedPages })
|
await augmentPages(pages, nuxt.vfs, { pagesToSkip: augmentedPages, ...augmentCtx })
|
||||||
augmentedPages?.clear()
|
augmentedPages?.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,13 +159,15 @@ export function generateRoutesFromFiles (files: ScannedFile[], options: Generate
|
|||||||
interface AugmentPagesContext {
|
interface AugmentPagesContext {
|
||||||
pagesToSkip?: Set<string>
|
pagesToSkip?: Set<string>
|
||||||
augmentedPages?: Set<string>
|
augmentedPages?: Set<string>
|
||||||
|
extraExtractionKeys?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function augmentPages (routes: NuxtPage[], vfs: Record<string, string>, ctx: AugmentPagesContext = {}) {
|
export async function augmentPages (routes: NuxtPage[], vfs: Record<string, string>, ctx: AugmentPagesContext = {}) {
|
||||||
ctx.augmentedPages ??= new Set()
|
ctx.augmentedPages ??= new Set()
|
||||||
for (const route of routes) {
|
for (const route of routes) {
|
||||||
if (route.file && !ctx.pagesToSkip?.has(route.file)) {
|
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 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) {
|
if (route.meta) {
|
||||||
routeMeta.meta = { ...routeMeta.meta, ...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 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 DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const
|
||||||
|
|
||||||
const pageContentsCache: Record<string, string> = {}
|
const pageContentsCache: Record<string, string> = {}
|
||||||
const metaCache: Record<string, Partial<Record<keyof NuxtPage, any>>> = {}
|
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
|
// set/update pageContentsCache, invalidate metaCache on cache mismatch
|
||||||
if (!(absolutePath in pageContentsCache) || pageContentsCache[absolutePath] !== contents) {
|
if (!(absolutePath in pageContentsCache) || pageContentsCache[absolutePath] !== contents) {
|
||||||
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 extractedMeta = {} as Partial<Record<keyof NuxtPage, any>>
|
||||||
|
|
||||||
|
const extractionKeys = new Set<keyof NuxtPage>([...defaultExtractionKeys, ...extraExtractionKeys as Array<keyof NuxtPage>])
|
||||||
|
|
||||||
for (const script of scriptBlocks) {
|
for (const script of scriptBlocks) {
|
||||||
if (!PAGE_META_RE.test(script.code)) {
|
if (!PAGE_META_RE.test(script.code)) {
|
||||||
continue
|
continue
|
||||||
@ -295,7 +300,7 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const name = property.key.type === 'Identifier' ? property.key.name : String(property.value)
|
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')
|
dynamicProperties.add('meta')
|
||||||
break
|
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', () => {
|
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
|
* 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
|
* performance improvement when prerendering sites that use `useAsyncData` or `useFetch` and fetch the same
|
||||||
|
Loading…
Reference in New Issue
Block a user