diff --git a/packages/next/src/server/app-render/entry-base.ts b/packages/next/src/server/app-render/entry-base.ts index 4a28c196a8a5f..1a27ff162a707 100644 --- a/packages/next/src/server/app-render/entry-base.ts +++ b/packages/next/src/server/app-render/entry-base.ts @@ -58,6 +58,20 @@ if (process.env.NODE_ENV === 'development') { SegmentViewStateNode = mod.SegmentViewStateNode } +// For hot-reloader +declare global { + var __next__clear_chunk_cache__: (() => void) | null | undefined + var __turbopack_clear_chunk_cache__: () => void | null | undefined +} +// hot-reloader modules are not bundled so we need to inject `__next__clear_chunk_cache__` +// into globalThis from this file which is bundled. +if (process.env.TURBOPACK) { + globalThis.__next__clear_chunk_cache__ = __turbopack_clear_chunk_cache__ +} else { + // Webpack does not have chunks on the server + globalThis.__next__clear_chunk_cache__ = null +} + // patchFetch makes use of APIs such as `React.unstable_postpone` which are only available // in the experimental channel of React, so export it from here so that it comes from the bundled runtime export function patchFetch() { diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 73b5b6b01e8c9..24d143a0cd4e5 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -1463,7 +1463,7 @@ export const defaultConfig = Object.freeze({ useCache: undefined, slowModuleDetection: undefined, globalNotFound: false, - devtoolSegmentExplorer: false, + devtoolSegmentExplorer: true, browserDebugInfoInTerminal: false, optimizeRouterScrolling: false, strictNextHead: true, diff --git a/packages/next/src/server/dev/hot-reloader-turbopack.ts b/packages/next/src/server/dev/hot-reloader-turbopack.ts index e58a792e1ae00..0d12b03db8f0e 100644 --- a/packages/next/src/server/dev/hot-reloader-turbopack.ts +++ b/packages/next/src/server/dev/hot-reloader-turbopack.ts @@ -109,6 +109,8 @@ const isTestMode = !!( const sessionId = Math.floor(Number.MAX_SAFE_INTEGER * Math.random()) +declare const __next__clear_chunk_cache__: (() => void) | null | undefined + /** * Replaces turbopack:///[project] with the specified project in the `source` field. */ @@ -342,10 +344,11 @@ export async function createHotReloaderTurbopack( resetFetch() - // Edge uses the browser runtime which already disposes chunks individually. - // TODO: process.env.NEXT_RUNTIME is 'nodejs' even though Node.js runtime is not used. - if ('__turbopack_clear_chunk_cache__' in globalThis) { - ;(globalThis as any).__turbopack_clear_chunk_cache__() + // Not available in: + // - Pages Router (no server-side HMR) + // - Edge Runtime (uses browser runtime which already disposes chunks individually) + if (typeof __next__clear_chunk_cache__ === 'function') { + __next__clear_chunk_cache__() } const serverPaths = writtenEndpoint.serverPaths.map(({ path: p }) => diff --git a/test/development/acceptance-app/hydration-error.test.ts b/test/development/acceptance-app/hydration-error.test.ts index 56c0205fbc877..7610a80ad219d 100644 --- a/test/development/acceptance-app/hydration-error.test.ts +++ b/test/development/acceptance-app/hydration-error.test.ts @@ -73,23 +73,26 @@ describe('Error overlay for hydration errors in App router', () => { await expect(browser).toDisplayCollapsedRedbox(` { "componentStack": "... - - - - - - - - - - + + + + + } forbidden={undefined} unauthorized={undefined}> + } forbidden={undefined} ...> + + + + +
+ client - server - ...", + ... + ... + ...", "description": "Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:", "environmentLabel": null, "label": "Recoverable Error", @@ -150,21 +153,24 @@ describe('Error overlay for hydration errors in App router', () => { await expect(browser).toDisplayCollapsedRedbox(` { "componentStack": "... - - - - - - - - - - + + + + + } forbidden={undefined} unauthorized={undefined}> + } forbidden={undefined} ...> + + + + +
+
- ...", + ... + ... + ...", "description": "Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:", "environmentLabel": null, "label": "Recoverable Error", @@ -217,14 +223,16 @@ describe('Error overlay for hydration errors in App router', () => { -