diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index 824dc200b1ee..b7b63ecfc25f 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -1301,7 +1301,14 @@ export async function renderToHTML( } } - if ((isServerComponent || process.browser) && Document.getInitialProps) { + if ( + // If it's server component, edge runtime or using default document with react 18, + // try to fallback to built-in functional document + (isServerComponent || + process.browser || + (builtinDocument && hasConcurrentFeatures)) && + Document.getInitialProps + ) { if (builtinDocument) { Document = builtinDocument } else { diff --git a/test/integration/react-18/app/pages/index.js b/test/integration/react-18/app/pages/index.js index 205e6b099767..01390f50201f 100644 --- a/test/integration/react-18/app/pages/index.js +++ b/test/integration/react-18/app/pages/index.js @@ -1,7 +1,13 @@ import ReactDOM from 'react-dom' import Image from 'next/image' +function sideEffectCall() { + console.log('sideEffectCall') +} + export default function Index() { + sideEffectCall() + if (typeof window !== 'undefined') { window.didHydrate = true } diff --git a/test/integration/react-18/test/basics.js b/test/integration/react-18/test/basics.js index 8ef1800548ed..503da56d4502 100644 --- a/test/integration/react-18/test/basics.js +++ b/test/integration/react-18/test/basics.js @@ -5,6 +5,14 @@ import cheerio from 'cheerio' import { renderViaHTTP } from 'next-test-utils' export default (context, env) => { + it('should render page on server side only once if there is no custom document', async () => { + await renderViaHTTP(context.appPort, '/') + const firstIndex = context.stdout.indexOf('sideEffectCall') + const lastIndex = context.stdout.lastIndexOf('sideEffectCall') + // log only once + expect(firstIndex === lastIndex).toBe(true) + }) + it('no warnings for image related link props', async () => { await renderViaHTTP(context.appPort, '/') expect(context.stderr).not.toContain('Warning: Invalid DOM property') diff --git a/test/lib/next-test-utils.js b/test/lib/next-test-utils.js index 589dd66b6899..889e1e16ba5b 100644 --- a/test/lib/next-test-utils.js +++ b/test/lib/next-test-utils.js @@ -754,10 +754,10 @@ function runSuite(suiteName, context, options) { describe(`${suiteName} ${env}`, () => { beforeAll(async () => { options.beforeAll?.(env) + context.stdout = '' context.stderr = '' - const onStderr = (msg) => { - context.stderr += msg - } + const onStdout = (msg) => (context.stdout += msg) + const onStderr = (msg) => (context.stderr += msg) if (env === 'prod') { context.appPort = await findPort() const { stdout, stderr, code } = await nextBuild(appDir, [], { @@ -768,11 +768,13 @@ function runSuite(suiteName, context, options) { context.stderr = stderr context.code = code context.server = await nextStart(context.appDir, context.appPort, { + onStdout, onStderr, }) } else if (env === 'dev') { context.appPort = await findPort() context.server = await launchApp(context.appDir, context.appPort, { + onStdout, onStderr, }) }