From 9cfc797bb7439735cc171fd459fd6f45a11fdce7 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 13 Feb 2025 12:32:15 -0700 Subject: [PATCH] [ppr] Improve experimental debugging (#76016) This fixes a bug with the experimental PPR debugging where it previously always failed in production because the hydration script was always invoked even when the stream was terminated early due to the debugging state. --- .../webpack/plugins/define-env-plugin.ts | 4 ++ packages/next/src/client/app-bootstrap.ts | 21 +++++++++- .../next/src/server/app-render/app-render.tsx | 42 ++++--------------- packages/next/src/server/app-render/types.ts | 6 --- packages/next/src/server/base-server.ts | 1 - 5 files changed, 30 insertions(+), 44 deletions(-) diff --git a/packages/next/src/build/webpack/plugins/define-env-plugin.ts b/packages/next/src/build/webpack/plugins/define-env-plugin.ts index 96ea1e5776a35..f89b6ec5aa551 100644 --- a/packages/next/src/build/webpack/plugins/define-env-plugin.ts +++ b/packages/next/src/build/webpack/plugins/define-env-plugin.ts @@ -192,6 +192,10 @@ export function getDefineEnv({ 'process.env.__NEXT_DYNAMIC_IO': isDynamicIOEnabled, 'process.env.__NEXT_USE_CACHE': isUseCacheEnabled, 'process.env.NEXT_DEPLOYMENT_ID': config.deploymentId || false, + // Propagates the `__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING` environment + // variable to the client. + 'process.env.__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING': + process.env.__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING || false, 'process.env.__NEXT_FETCH_CACHE_KEY_PREFIX': fetchCacheKeyPrefix ?? '', ...(isTurbopack ? {} diff --git a/packages/next/src/client/app-bootstrap.ts b/packages/next/src/client/app-bootstrap.ts index 5baa7424877de..f422b50c5e695 100644 --- a/packages/next/src/client/app-bootstrap.ts +++ b/packages/next/src/client/app-bootstrap.ts @@ -56,8 +56,25 @@ function loadScriptsInSequence( }) } -export function appBootstrap(callback: () => void) { +export function appBootstrap(hydrate: () => void) { loadScriptsInSequence((self as any).__next_s, () => { - callback() + // If the static shell is being debugged, skip hydration if the + // `__nextppronly` query is present. This is only enabled when the + // environment variable `__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING` is + // set to `1`. Otherwise the following is optimized out. + if (process.env.__NEXT_EXPERIMENTAL_STATIC_SHELL_DEBUGGING === '1') { + const search = new URLSearchParams(window.location.search) + if ( + search.get('__nextppronly') === 'fallback' || + search.get('__nextppronly') === '1' + ) { + console.warn( + `Skipping hydration due to __nextppronly=${search.get('__nextppronly')}` + ) + return + } + } + + hydrate() }) } diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 947caf2fdc190..92dc38bbb649e 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1932,11 +1932,7 @@ async function renderToStream( }) }, maxHeadersLength: renderOpts.reactMaxHeadersLength, - // When debugging the static shell, client-side rendering should be - // disabled to prevent blanking out the page. - bootstrapScripts: renderOpts.isDebugStaticShell - ? [] - : [bootstrapScript], + bootstrapScripts: [bootstrapScript], formState, } ) @@ -2825,11 +2821,7 @@ async function prerenderToStream( ) } }, - // When debugging the static shell, client-side rendering should be - // disabled to prevent blanking out the page. - bootstrapScripts: renderOpts.isDebugStaticShell - ? [] - : [bootstrapScript], + bootstrapScripts: [bootstrapScript], } ), () => { @@ -2992,11 +2984,7 @@ async function prerenderToStream( }) }, maxHeadersLength: renderOpts.reactMaxHeadersLength, - // When debugging the static shell, client-side rendering should be - // disabled to prevent blanking out the page. - bootstrapScripts: renderOpts.isDebugStaticShell - ? [] - : [bootstrapScript], + bootstrapScripts: [bootstrapScript], } ), () => { @@ -3299,11 +3287,7 @@ async function prerenderToStream( ) } }, - // When debugging the static shell, client-side rendering should be - // disabled to prevent blanking out the page. - bootstrapScripts: renderOpts.isDebugStaticShell - ? [] - : [bootstrapScript], + bootstrapScripts: [bootstrapScript], } ) pendingInitialClientResult.catch((err: unknown) => { @@ -3457,11 +3441,7 @@ async function prerenderToStream( return htmlRendererErrorHandler(err, errorInfo) }, - // When debugging the static shell, client-side rendering should be - // disabled to prevent blanking out the page. - bootstrapScripts: renderOpts.isDebugStaticShell - ? [] - : [bootstrapScript], + bootstrapScripts: [bootstrapScript], } ), () => { @@ -3620,11 +3600,7 @@ async function prerenderToStream( }) }, maxHeadersLength: renderOpts.reactMaxHeadersLength, - // When debugging the static shell, client-side rendering should be - // disabled to prevent blanking out the page. - bootstrapScripts: renderOpts.isDebugStaticShell - ? [] - : [bootstrapScript], + bootstrapScripts: [bootstrapScript], } ) const getServerInsertedHTML = makeGetServerInsertedHTML({ @@ -3829,11 +3805,7 @@ async function prerenderToStream( { onError: htmlRendererErrorHandler, nonce: ctx.nonce, - // When debugging the static shell, client-side rendering should be - // disabled to prevent blanking out the page. - bootstrapScripts: renderOpts.isDebugStaticShell - ? [] - : [bootstrapScript], + bootstrapScripts: [bootstrapScript], } ) diff --git a/packages/next/src/server/app-render/types.ts b/packages/next/src/server/app-render/types.ts index 3c7361e6333cc..570906a5d07f2 100644 --- a/packages/next/src/server/app-render/types.ts +++ b/packages/next/src/server/app-render/types.ts @@ -233,12 +233,6 @@ export interface RenderOptsPartial { */ devRenderResumeDataCache?: RenderResumeDataCache - /** - * When true, only the static shell of the page will be rendered. This will - * also enable other debugging features such as logging in development. - */ - isDebugStaticShell?: boolean - /** * When true, the page will be rendered using the static rendering to detect * any dynamic API's that would have stopped the page from being fully diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 274806bea1678..2093b27799803 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -2546,7 +2546,6 @@ export default abstract class Server< renderOpts.supportsDynamicResponse = false renderOpts.isStaticGeneration = true renderOpts.isRevalidate = true - renderOpts.isDebugStaticShell = isDebugStaticShell renderOpts.isDebugDynamicAccesses = isDebugDynamicAccesses }