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 }