diff --git a/packages/next/src/lib/metadata/metadata.tsx b/packages/next/src/lib/metadata/metadata.tsx index 98c4c0e06587b..f817beb2143c8 100644 --- a/packages/next/src/lib/metadata/metadata.tsx +++ b/packages/next/src/lib/metadata/metadata.tsx @@ -21,10 +21,9 @@ import { } from './generate/opengraph' import { IconsMetadata } from './generate/icons' import { - resolveMetadataItems, - accumulateMetadata, - accumulateViewport, type MetadataErrorType, + resolveMetadata, + resolveViewport, } from './resolve-metadata' import { MetaFilter } from './generate/meta' import type { @@ -196,24 +195,14 @@ async function getResolvedMetadataImpl( errorType?: MetadataErrorType | 'redirect' ): Promise { const errorConvention = errorType === 'redirect' ? undefined : errorType - - const metadataItems = await resolveMetadataItems( + return renderMetadata( tree, searchParams, - errorConvention, getDynamicParamFromSegment, + metadataContext, createServerParamsForMetadata, - workStore - ) - const elements: Array = createMetadataElements( - await accumulateMetadata(metadataItems, metadataContext) - ) - return ( - <> - {elements.map((el, index) => { - return cloneElement(el as React.ReactElement, { key: index }) - })} - + workStore, + errorConvention ) } @@ -227,24 +216,14 @@ async function getNotFoundMetadataImpl( workStore: WorkStore ): Promise { const notFoundErrorConvention = 'not-found' - const notFoundMetadataItems = await resolveMetadataItems( + return renderMetadata( tree, searchParams, - notFoundErrorConvention, getDynamicParamFromSegment, + metadataContext, createServerParamsForMetadata, - workStore - ) - - const elements: Array = createMetadataElements( - await accumulateMetadata(notFoundMetadataItems, metadataContext) - ) - return ( - <> - {elements.map((el, index) => { - return cloneElement(el as React.ReactElement, { key: index }) - })} - + workStore, + notFoundErrorConvention ) } @@ -258,18 +237,55 @@ async function getResolvedViewportImpl( errorType?: MetadataErrorType | 'redirect' ): Promise { const errorConvention = errorType === 'redirect' ? undefined : errorType + return renderViewport( + tree, + searchParams, + getDynamicParamFromSegment, + createServerParamsForMetadata, + workStore, + errorConvention + ) +} - const metadataItems = await resolveMetadataItems( +const getNotFoundViewport = cache(getNotFoundViewportImpl) +async function getNotFoundViewportImpl( + tree: LoaderTree, + searchParams: Promise, + getDynamicParamFromSegment: GetDynamicParamFromSegment, + createServerParamsForMetadata: CreateServerParamsForMetadata, + workStore: WorkStore +): Promise { + const notFoundErrorConvention = 'not-found' + return renderViewport( tree, searchParams, - errorConvention, getDynamicParamFromSegment, createServerParamsForMetadata, - workStore + workStore, + notFoundErrorConvention ) - const elements: Array = createViewportElements( - await accumulateViewport(metadataItems) +} + +async function renderMetadata( + tree: LoaderTree, + searchParams: Promise, + getDynamicParamFromSegment: GetDynamicParamFromSegment, + metadataContext: MetadataContext, + createServerParamsForMetadata: CreateServerParamsForMetadata, + workStore: WorkStore, + errorConvention?: MetadataErrorType +) { + const resolvedMetadata = await resolveMetadata( + tree, + searchParams, + errorConvention, + getDynamicParamFromSegment, + createServerParamsForMetadata, + workStore, + metadataContext ) + const elements: Array = + createMetadataElements(resolvedMetadata) return ( <> {elements.map((el, index) => { @@ -279,26 +295,25 @@ async function getResolvedViewportImpl( ) } -const getNotFoundViewport = cache(getNotFoundViewportImpl) -async function getNotFoundViewportImpl( +async function renderViewport( tree: LoaderTree, searchParams: Promise, getDynamicParamFromSegment: GetDynamicParamFromSegment, createServerParamsForMetadata: CreateServerParamsForMetadata, - workStore: WorkStore -): Promise { - const notFoundErrorConvention = 'not-found' - const notFoundMetadataItems = await resolveMetadataItems( + workStore: WorkStore, + errorConvention?: MetadataErrorType +) { + const notFoundResolvedViewport = await resolveViewport( tree, searchParams, - notFoundErrorConvention, + errorConvention, getDynamicParamFromSegment, createServerParamsForMetadata, workStore ) const elements: Array = createViewportElements( - await accumulateViewport(notFoundMetadataItems) + notFoundResolvedViewport ) return ( <> diff --git a/packages/next/src/lib/metadata/resolve-metadata.ts b/packages/next/src/lib/metadata/resolve-metadata.ts index cd1a6457638c1..2cc4af36bbd03 100644 --- a/packages/next/src/lib/metadata/resolve-metadata.ts +++ b/packages/next/src/lib/metadata/resolve-metadata.ts @@ -470,9 +470,7 @@ async function collectMetadata({ } } -const cachedResolveMetadataItems = cache(resolveMetadataItems) -export { cachedResolveMetadataItems as resolveMetadataItems } -async function resolveMetadataItems( +const resolveMetadataItems = cache(async function ( tree: LoaderTree, searchParams: Promise, errorConvention: MetadataErrorType | undefined, @@ -496,7 +494,7 @@ async function resolveMetadataItems( createServerParamsForMetadata, workStore ) -} +}) async function resolveMetadataItemsImpl( metadataItems: MetadataItems, @@ -901,3 +899,44 @@ export async function accumulateViewport( } return resolvedViewport } + +// Exposed API for metadata component, that directly resolve the loader tree and related context as resolved metadata. +export async function resolveMetadata( + tree: LoaderTree, + searchParams: Promise, + errorConvention: MetadataErrorType | undefined, + getDynamicParamFromSegment: GetDynamicParamFromSegment, + createServerParamsForMetadata: CreateServerParamsForMetadata, + workStore: WorkStore, + metadataContext: MetadataContext +): Promise { + const metadataItems = await resolveMetadataItems( + tree, + searchParams, + errorConvention, + getDynamicParamFromSegment, + createServerParamsForMetadata, + workStore + ) + return accumulateMetadata(metadataItems, metadataContext) +} + +// Exposed API for viewport component, that directly resolve the loader tree and related context as resolved viewport. +export async function resolveViewport( + tree: LoaderTree, + searchParams: Promise, + errorConvention: MetadataErrorType | undefined, + getDynamicParamFromSegment: GetDynamicParamFromSegment, + createServerParamsForMetadata: CreateServerParamsForMetadata, + workStore: WorkStore +): Promise { + const metadataItems = await resolveMetadataItems( + tree, + searchParams, + errorConvention, + getDynamicParamFromSegment, + createServerParamsForMetadata, + workStore + ) + return accumulateViewport(metadataItems) +}