From 236e00144e776b641d0251fe390626ab736121cc Mon Sep 17 00:00:00 2001 From: Josh Story Date: Mon, 21 Oct 2024 17:23:12 -0700 Subject: [PATCH] [dynamicIO] Update prerender to use Fizz prerender (#71580) Previously the `prerender` function for Fizz was gated to experimental but in our latest React sync we now have access to it in the canary channel. This updates the prerender pathway for non-experimental react to use `prerender` rather than `renderToReadableStream`. `prerender` has a few benefits in that it does breadth first rendering at Suspense boundaries so you can ensure fallback UIs are fully rendered wherever possible if you end up abortint the render. currently stacked on #71579 --- .../next/src/server/app-render/app-render.tsx | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index b8bf2be5da163..103e79c6a1ac1 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -2028,8 +2028,8 @@ async function spawnDynamicValidationInDev( const { ServerInsertedHTMLProvider } = createServerInsertedHTML() const nonce = '1' - const renderToReadableStream = require('react-dom/server.edge') - .renderToReadableStream as (typeof import('react-dom/server.edge'))['renderToReadableStream'] + const prerender = require('react-dom/static.edge') + .prerender as (typeof import('react-dom/static.edge'))['prerender'] let clientDynamicTracking = createDynamicTrackingState(false) let dynamicValidation = createDynamicValidationState() @@ -2081,29 +2081,30 @@ async function spawnDynamicValidationInDev( let hadException = false try { await prerenderAndAbortInSequentialTasks( - () => { - const pendingHTMLStream = workUnitAsyncStorage.run( - firstAttemptClientPrerenderStore, - renderToReadableStream, - {}} - clientReferenceManifest={clientReferenceManifest} - ServerInsertedHTMLProvider={ServerInsertedHTMLProvider} - nonce={nonce} - />, - { - signal: firstAttemptClientController.signal, - onError: SSROnError, - } - ) - pendingHTMLStream.catch(() => {}) - return pendingHTMLStream + async () => { + workUnitAsyncStorage + .run( + firstAttemptClientPrerenderStore, + prerender, + {}} + clientReferenceManifest={clientReferenceManifest} + ServerInsertedHTMLProvider={ServerInsertedHTMLProvider} + nonce={nonce} + />, + { + signal: firstAttemptClientController.signal, + onError: SSROnError, + } + ) + .catch(() => {}) + return null }, () => { firstAttemptClientController.abort() } - ) + ).catch(() => {}) } catch (err: unknown) { if (firstAttemptClientController.signal.aborted) { // We aborted the render normally and can ignore this error @@ -2153,7 +2154,7 @@ async function spawnDynamicValidationInDev( workUnitAsyncStorage .run( secondAttemptClientPrerenderStore, - renderToReadableStream, + prerender, {}} @@ -2167,6 +2168,7 @@ async function spawnDynamicValidationInDev( } ) .catch(() => {}) + return null }, () => { secondAttemptClientController.abort() @@ -3009,7 +3011,7 @@ async function prerenderToStream( let htmlStream try { htmlStream = await prerenderAndAbortInSequentialTasks( - () => { + async () => { const teedStream = ( workUnitAsyncStorage.run( // The store to scope @@ -3029,11 +3031,11 @@ async function prerenderToStream( reactServerStream = teedStream[0] const rscForSSRStream = teedStream[1] - const renderToReadableStream = require('react-dom/server.edge') - .renderToReadableStream as (typeof import('react-dom/server.edge'))['renderToReadableStream'] - const pendingHTMLStream = workUnitAsyncStorage.run( + const prerender = require('react-dom/static.edge') + .prerender as (typeof import('react-dom/static.edge'))['prerender'] + const { prelude } = await workUnitAsyncStorage.run( ssrPrerenderStore, - renderToReadableStream, + prerender, {}) - return pendingHTMLStream + return prelude }, () => { SSRController.abort(abortReason)