Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[metadata] new metadata insertion API and support PPR" #75858

Merged
merged 1 commit into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,9 @@ function finishPendingCacheNode(
// a pending promise that needs to be resolved with the dynamic head from
// the server.
const head = cacheNode.head
// TODO: change head back to ReactNode when metadata
// is stably rendered in body
// Handle head[0] - viewport
if (isDeferredRsc(head)) {
head.resolve(dynamicHead)
}
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/export/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export interface ExportPageInput {
nextConfigOutput?: NextConfigComplete['output']
enableExperimentalReact?: boolean
sriEnabled: boolean
streamingMetadata: boolean | undefined
}

export type ExportRouteResult =
Expand Down
9 changes: 0 additions & 9 deletions packages/next/src/export/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,6 @@ async function exportPageImpl(
)
}

// During the export phase in next build, if it's using PPR we can serve streaming metadata
// when it's available. When we're building the PPR rendering result, we don't need to rely
// on the user agent. The result can be determined to serve streaming on infrastructure level.
const serveStreamingMetadata = Boolean(
isRoutePPREnabled && input.streamingMetadata
)

const renderOpts: WorkerRenderOpts = {
...components,
...input.renderOpts,
Expand All @@ -269,7 +262,6 @@ async function exportPageImpl(
disableOptimizedLoading,
locale,
supportsDynamicResponse: false,
serveStreamingMetadata,
experimental: {
...input.renderOpts.experimental,
isRoutePPREnabled,
Expand Down Expand Up @@ -424,7 +416,6 @@ export async function exportPages(
debugOutput: options.debugOutput,
enableExperimentalReact: needsExperimentalReact(nextConfig),
sriEnabled: Boolean(nextConfig.experimental.sri?.algorithm),
streamingMetadata: nextConfig.experimental.streamingMetadata,
buildId: input.buildId,
}),
// If exporting the page takes longer than the timeout, reject the promise.
Expand Down
22 changes: 15 additions & 7 deletions packages/next/src/lib/metadata/async-metadata.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
'use client'

import { use, type JSX } from 'react'
import { useServerInsertedMetadata } from '../../server/app-render/metadata-insertion/use-server-inserted-metadata'
import { use } from 'react'
import { useServerInsertedHTML } from '../../client/components/navigation'

function ServerInsertMetadata({ promise }: { promise: Promise<JSX.Element> }) {
// Apply use() to the metadata promise to suspend the rendering in SSR.
const metadata = use(promise)
// Insert metadata into the HTML stream through the `useServerInsertedMetadata`
useServerInsertedMetadata(() => metadata)
// We need to wait for metadata on server once it's resolved, and insert into
// the HTML through `useServerInsertedHTML`. It will suspense in <head> during SSR.
function ServerInsertMetadata({ promise }: { promise: Promise<any> }) {
let metadataToFlush: React.ReactNode = use(promise)

useServerInsertedHTML(() => {
if (metadataToFlush) {
const flushing = metadataToFlush
// reset to null to ensure we only flush it once
metadataToFlush = null
return flushing
}
})

return null
}
Expand Down
29 changes: 6 additions & 23 deletions packages/next/src/lib/metadata/metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { GetDynamicParamFromSegment } from '../../server/app-render/app-ren
import type { LoaderTree } from '../../server/lib/app-dir-module'
import type { CreateServerParamsForMetadata } from '../../server/request/params'

import { Suspense, cache, cloneElement } from 'react'
import { cache, cloneElement } from 'react'
import {
AppleWebAppMeta,
FormatDetectionMeta,
Expand Down Expand Up @@ -38,7 +38,6 @@ import {
VIEWPORT_BOUNDARY_NAME,
} from './metadata-constants'
import { AsyncMetadata } from './async-metadata'
import { isPostpone } from '../../server/lib/router-utils/is-postpone'

// Use a promise to share the status of the metadata resolving,
// returning two components `MetadataTree` and `MetadataOutlet`
Expand Down Expand Up @@ -148,8 +147,8 @@ export function createMetadataComponents({
async function resolveFinalMetadata() {
try {
return await metadata()
} catch (metadataErr) {
if (!errorType && isHTTPAccessFallbackError(metadataErr)) {
} catch (error) {
if (!errorType && isHTTPAccessFallbackError(error)) {
try {
return await getNotFoundMetadata(
tree,
Expand All @@ -159,18 +158,7 @@ export function createMetadataComponents({
createServerParamsForMetadata,
workStore
)
} catch (notFoundMetadataErr) {
// In PPR rendering we still need to throw the postpone error.
// If metadata is postponed, React needs to be aware of the location of error.
if (isPostpone(notFoundMetadataErr)) {
throw notFoundMetadataErr
}
}
}
// In PPR rendering we still need to throw the postpone error.
// If metadata is postponed, React needs to be aware of the location of error.
if (isPostpone(metadataErr)) {
throw metadataErr
} catch {}
}
// We don't actually want to error in this component. We will
// also error in the MetadataOutlet which causes the error to
Expand All @@ -180,15 +168,10 @@ export function createMetadataComponents({
}
}
async function Metadata() {
const promise = resolveFinalMetadata()
if (serveStreamingMetadata) {
return (
<Suspense fallback={null}>
<AsyncMetadata promise={promise} />
</Suspense>
)
return <AsyncMetadata promise={resolveFinalMetadata()} />
}
return await promise
return await resolveFinalMetadata()
}

Metadata.displayName = METADATA_BOUNDARY_NAME
Expand Down
Loading
Loading