mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-21 21:25:11 +00:00
feat(nuxt,schema): pages:resolved
hook + scan meta post extend (#28861)
This commit is contained in:
parent
cd8a124123
commit
eaeda4ee1e
@ -67,6 +67,7 @@ export default defineNuxtConfig({
|
|||||||
// app: 'app'
|
// app: 'app'
|
||||||
// },
|
// },
|
||||||
// experimental: {
|
// experimental: {
|
||||||
|
// scanPageMeta: 'after-resolve',
|
||||||
// sharedPrerenderData: false,
|
// sharedPrerenderData: false,
|
||||||
// compileTemplate: true,
|
// compileTemplate: true,
|
||||||
// resetAsyncDataToUndefined: true,
|
// resetAsyncDataToUndefined: true,
|
||||||
@ -236,6 +237,45 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Scan Page Meta After Resolution
|
||||||
|
|
||||||
|
🚦 **Impact Level**: Minimal
|
||||||
|
|
||||||
|
##### What Changed
|
||||||
|
|
||||||
|
We now scan page metadata (defined in `definePageMeta`) _after_ calling the `pages:extend` hook rather than before.
|
||||||
|
|
||||||
|
##### Reasons for Change
|
||||||
|
|
||||||
|
This was to allow scanning metadata for pages that users wanted to add in `pages:extend`. We still offer an opportunity to change or override page metadata in a new `pages:resolved` hook.
|
||||||
|
|
||||||
|
##### Migration Steps
|
||||||
|
|
||||||
|
If you want to override page metadata, do that in `pages:resolved` rather than in `pages:extend`.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
hooks: {
|
||||||
|
- 'pages:extend'(pages) {
|
||||||
|
+ 'pages:resolved'(pages) {
|
||||||
|
const myPage = pages.find(page => page.path === '/')
|
||||||
|
myPage.meta ||= {}
|
||||||
|
myPage.meta.layout = 'overridden-layout'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can revert to the previous behaviour with:
|
||||||
|
|
||||||
|
```ts twoslash [nuxt.config.ts]
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
experimental: {
|
||||||
|
scanPageMeta: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
#### Shared Prerender Data
|
#### Shared Prerender Data
|
||||||
|
|
||||||
🚦 **Impact Level**: Medium
|
🚦 **Impact Level**: Medium
|
||||||
|
@ -334,6 +334,8 @@ 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.
|
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.
|
||||||
|
|
||||||
|
It is also possible to scan page metadata only after all routes have been registered in `pages:extend`. Then another hook, `pages:resolved` will be called. To enable this behavior, set `scanPageMeta: 'after-resolve'`.
|
||||||
|
|
||||||
You can disable this feature if it causes issues in your project.
|
You can disable this feature if it causes issues in your project.
|
||||||
|
|
||||||
```ts twoslash [nuxt.config.ts]
|
```ts twoslash [nuxt.config.ts]
|
||||||
|
@ -61,6 +61,7 @@ export default defineNuxtConfig({
|
|||||||
app: 'app'
|
app: 'app'
|
||||||
},
|
},
|
||||||
experimental: {
|
experimental: {
|
||||||
|
scanPageMeta: 'after-resolve',
|
||||||
sharedPrerenderData: false,
|
sharedPrerenderData: false,
|
||||||
compileTemplate: true,
|
compileTemplate: true,
|
||||||
resetAsyncDataToUndefined: true,
|
resetAsyncDataToUndefined: true,
|
||||||
|
@ -503,7 +503,7 @@ export default defineNuxtModule({
|
|||||||
const { routes, imports } = normalizeRoutes(app.pages, new Set(), {
|
const { routes, imports } = normalizeRoutes(app.pages, new Set(), {
|
||||||
serverComponentRuntime,
|
serverComponentRuntime,
|
||||||
clientComponentRuntime,
|
clientComponentRuntime,
|
||||||
overrideMeta: nuxt.options.experimental.scanPageMeta,
|
overrideMeta: !!nuxt.options.experimental.scanPageMeta,
|
||||||
})
|
})
|
||||||
return [...imports, `export default ${routes}`].join('\n')
|
return [...imports, `export default ${routes}`].join('\n')
|
||||||
},
|
},
|
||||||
|
@ -64,18 +64,25 @@ export async function resolvePagesRoutes (): Promise<NuxtPage[]> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const pages = uniqueBy(allRoutes, 'path')
|
const pages = uniqueBy(allRoutes, 'path')
|
||||||
|
|
||||||
const shouldAugment = nuxt.options.experimental.scanPageMeta || nuxt.options.experimental.typedPages
|
const shouldAugment = nuxt.options.experimental.scanPageMeta || nuxt.options.experimental.typedPages
|
||||||
|
|
||||||
if (shouldAugment) {
|
if (shouldAugment === false) {
|
||||||
|
await nuxt.callHook('pages:extend', pages)
|
||||||
|
return pages
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldAugment === 'after-resolve') {
|
||||||
|
await nuxt.callHook('pages:extend', pages)
|
||||||
|
await augmentPages(pages, nuxt.vfs)
|
||||||
|
} else {
|
||||||
const augmentedPages = await augmentPages(pages, nuxt.vfs)
|
const augmentedPages = await augmentPages(pages, nuxt.vfs)
|
||||||
await nuxt.callHook('pages:extend', pages)
|
await nuxt.callHook('pages:extend', pages)
|
||||||
await augmentPages(pages, nuxt.vfs, augmentedPages)
|
await augmentPages(pages, nuxt.vfs, augmentedPages)
|
||||||
augmentedPages.clear()
|
augmentedPages.clear()
|
||||||
} else {
|
|
||||||
await nuxt.callHook('pages:extend', pages)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await nuxt.callHook('pages:resolved', pages)
|
||||||
|
|
||||||
return pages
|
return pages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,8 +297,13 @@ export default defineUntypedSchema({
|
|||||||
* This only works with static or strings/arrays rather than variables or conditional assignment.
|
* This only works with static or strings/arrays rather than variables or conditional assignment.
|
||||||
*
|
*
|
||||||
* @see [Nuxt Issues #24770](https://github.com/nuxt/nuxt/issues/24770)
|
* @see [Nuxt Issues #24770](https://github.com/nuxt/nuxt/issues/24770)
|
||||||
|
* @type {boolean | 'after-resolve'}
|
||||||
*/
|
*/
|
||||||
scanPageMeta: true,
|
scanPageMeta: {
|
||||||
|
async $resolve (val, get) {
|
||||||
|
return val ?? ((await get('future') as Record<string, unknown>).compatibilityVersion === 4 ? 'after-resolve' : true)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
@ -183,12 +183,19 @@ export interface NuxtHooks {
|
|||||||
'builder:watch': (event: WatchEvent, path: string) => HookResult
|
'builder:watch': (event: WatchEvent, path: string) => HookResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after pages routes are resolved.
|
* Called after page routes are scanned from the file system.
|
||||||
* @param pages Array containing resolved pages
|
* @param pages Array containing scanned pages
|
||||||
* @returns Promise
|
* @returns Promise
|
||||||
*/
|
*/
|
||||||
'pages:extend': (pages: NuxtPage[]) => HookResult
|
'pages:extend': (pages: NuxtPage[]) => HookResult
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after page routes have been augmented with scanned metadata.
|
||||||
|
* @param pages Array containing resolved pages
|
||||||
|
* @returns Promise
|
||||||
|
*/
|
||||||
|
'pages:resolved': (pages: NuxtPage[]) => HookResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when resolving `app/router.options` files. It allows modifying the detected router options files
|
* Called when resolving `app/router.options` files. It allows modifying the detected router options files
|
||||||
* and adding new ones.
|
* and adding new ones.
|
||||||
|
@ -13,13 +13,18 @@ export default defineNuxtModule({
|
|||||||
name: 'page-extend',
|
name: 'page-extend',
|
||||||
path: '/page-extend',
|
path: '/page-extend',
|
||||||
file: resolver.resolve('../runtime/page.vue'),
|
file: resolver.resolve('../runtime/page.vue'),
|
||||||
}, {
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
nuxt.hook('pages:resolved', (pages) => {
|
||||||
|
pages.push({
|
||||||
path: '/big-page-1',
|
path: '/big-page-1',
|
||||||
file: resolver.resolve('./pages/big-page.vue'),
|
file: resolver.resolve('./pages/big-page.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
layout: false,
|
layout: false,
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
path: '/big-page-2',
|
path: '/big-page-2',
|
||||||
file: resolver.resolve('./pages/big-page.vue'),
|
file: resolver.resolve('./pages/big-page.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
|
4
test/fixtures/basic/nuxt.config.ts
vendored
4
test/fixtures/basic/nuxt.config.ts
vendored
@ -75,7 +75,7 @@ export default defineNuxtConfig({
|
|||||||
_layout: page.meta?.layout,
|
_layout: page.meta?.layout,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
nuxt.hook('pages:extend', (pages) => {
|
nuxt.hook('pages:resolved', (pages) => {
|
||||||
const newPages = []
|
const newPages = []
|
||||||
for (const page of pages) {
|
for (const page of pages) {
|
||||||
if (routesToDuplicate.includes(page.path)) {
|
if (routesToDuplicate.includes(page.path)) {
|
||||||
@ -88,7 +88,7 @@ export default defineNuxtConfig({
|
|||||||
},
|
},
|
||||||
function (_options, nuxt) {
|
function (_options, nuxt) {
|
||||||
// to check that page metadata is preserved
|
// to check that page metadata is preserved
|
||||||
nuxt.hook('pages:extend', (pages) => {
|
nuxt.hook('pages:resolved', (pages) => {
|
||||||
const customName = pages.find(page => page.name === 'some-custom-name')
|
const customName = pages.find(page => page.name === 'some-custom-name')
|
||||||
if (!customName) { throw new Error('Page with custom name not found') }
|
if (!customName) { throw new Error('Page with custom name not found') }
|
||||||
if (customName.path !== '/some-custom-path') { throw new Error('Page path not extracted') }
|
if (customName.path !== '/some-custom-path') { throw new Error('Page path not extracted') }
|
||||||
|
Loading…
Reference in New Issue
Block a user