From 98af4de3fc8c5f4fd481c06b2bbcc14b2d8e268f Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Fri, 11 Mar 2022 10:51:55 +0100 Subject: [PATCH 01/12] make concurrent features independent from the global runtime option --- packages/next/build/entries.ts | 3 -- packages/next/build/index.ts | 34 +++++++++++++------ packages/next/build/webpack-config.ts | 13 +++---- packages/next/pages/_document.tsx | 4 +-- packages/next/server/dev/hot-reloader.ts | 13 ++++--- packages/next/server/dev/next-dev-server.ts | 3 +- packages/next/server/next-server.ts | 17 ++++++---- packages/next/server/render.tsx | 5 +-- packages/next/shared/lib/html-context.ts | 1 + .../react-18-invalid-config/index.test.js | 24 ++++++------- 10 files changed, 70 insertions(+), 47 deletions(-) diff --git a/packages/next/build/entries.ts b/packages/next/build/entries.ts index 3d0047efc9bdb..880c0a45dd277 100644 --- a/packages/next/build/entries.ts +++ b/packages/next/build/entries.ts @@ -176,9 +176,6 @@ export async function getPageRuntime( if (!pageRuntime) { if (isRuntimeRequired) { pageRuntime = globalRuntimeFallback - } else { - // @TODO: Remove this branch to fully implement the RFC. - pageRuntime = globalRuntimeFallback } } diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 25cf163cb6e49..0b1ed5dc5ab1f 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -75,7 +75,11 @@ import { } from '../telemetry/events' import { Telemetry } from '../telemetry/storage' import { CompilerResult, runCompiler } from './compiler' -import { createEntrypoints, createPagesMapping } from './entries' +import { + createEntrypoints, + createPagesMapping, + getPageRuntime, +} from './entries' import { generateBuildId } from './generate-build-id' import { isWriteable } from './is-writeable' import * as Log from './output/log' @@ -152,11 +156,10 @@ export default async function build( setGlobal('phase', PHASE_PRODUCTION_BUILD) setGlobal('distDir', distDir) - // Currently, when the runtime option is set (either `nodejs` or `edge`), - // we enable concurrent features (Fizz-related rendering architecture). - const runtime = config.experimental.runtime + // We enable concurrent features (Fizz-related rendering architecture) when + // using React 18 or experimental. const hasReactRoot = shouldUseReactRoot() - const hasConcurrentFeatures = !!runtime + const hasConcurrentFeatures = hasReactRoot const hasServerComponents = hasReactRoot && !!config.experimental.serverComponents @@ -622,6 +625,7 @@ export default async function build( entrypoints: entrypoints.client, rewrites, runWebpackSpan, + hasReactRoot, }), getBaseWebpackConfig(dir, { buildId, @@ -633,6 +637,7 @@ export default async function build( entrypoints: entrypoints.server, rewrites, runWebpackSpan, + hasReactRoot, }), hasReactRoot ? getBaseWebpackConfig(dir, { @@ -646,6 +651,7 @@ export default async function build( entrypoints: entrypoints.edgeServer, rewrites, runWebpackSpan, + hasReactRoot, }) : null, ]) @@ -954,10 +960,21 @@ export default async function build( let ssgPageRoutes: string[] | null = null let isMiddlewareRoute = !!page.match(MIDDLEWARE_ROUTE) + const pagePath = pagePaths.find((path) => + path.startsWith(actualPage + '.') + ) + const pageRuntime = pagePath + ? await getPageRuntime( + join(pagesDir, pagePath), + config.experimental.runtime + ) + : null + if ( !isMiddlewareRoute && !isReservedPage(page) && - !hasConcurrentFeatures + // We currently don't support staic optimization in the Edge runtime. + pageRuntime !== 'edge' ) { try { let isPageStaticSpan = @@ -1483,10 +1500,7 @@ export default async function build( const combinedPages = [...staticPages, ...ssgPages] - if ( - !hasConcurrentFeatures && - (combinedPages.length > 0 || useStatic404 || useDefaultStatic500) - ) { + if (combinedPages.length > 0 || useStatic404 || useDefaultStatic500) { const staticGenerationSpan = nextBuildSpan.traceChild('static-generation') await staticGenerationSpan.traceAsyncFn(async () => { detectConflictingPaths( diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 4e480e73f1076..003c2c375eeba 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -48,7 +48,6 @@ import type { Span } from '../trace' import { getRawPageExtensions } from './utils' import browserslist from 'next/dist/compiled/browserslist' import loadJsConfig from './load-jsconfig' -import { shouldUseReactRoot } from '../server/config' import { getMiddlewareSourceMapPlugins } from './webpack/plugins/middleware-source-maps-plugin' const watchOptions = Object.freeze({ @@ -310,6 +309,7 @@ export default async function getBaseWebpackConfig( rewrites, isDevFallback = false, runWebpackSpan, + hasReactRoot, }: { buildId: string config: NextConfigComplete @@ -323,6 +323,7 @@ export default async function getBaseWebpackConfig( rewrites: CustomRoutes['rewrites'] isDevFallback?: boolean runWebpackSpan: Span + hasReactRoot: boolean } ): Promise { const { useTypeScript, jsConfig, resolvedBaseUrl } = await loadJsConfig( @@ -335,10 +336,10 @@ export default async function getBaseWebpackConfig( rewrites.afterFiles.length > 0 || rewrites.fallback.length > 0 const hasReactRefresh: boolean = dev && !isServer - const hasReactRoot = shouldUseReactRoot() + const runtime = config.experimental.runtime - // Make sure reactRoot is enabled when react 18 is detected + // Make sure `reactRoot` is enabled when React 18 or experimental is detected. if (hasReactRoot) { config.experimental.reactRoot = true } @@ -353,14 +354,14 @@ export default async function getBaseWebpackConfig( '`experimental.runtime` requires `experimental.reactRoot` to be enabled along with React 18.' ) } - if (config.experimental.serverComponents && !runtime) { + if (config.experimental.serverComponents && !hasReactRoot) { throw new Error( - '`experimental.runtime` is required to be set along with `experimental.serverComponents`.' + '`experimental.serverComponents` requires React 18 to be installed.' ) } const targetWeb = isEdgeRuntime || !isServer - const hasConcurrentFeatures = !!runtime && hasReactRoot + const hasConcurrentFeatures = hasReactRoot const hasServerComponents = hasConcurrentFeatures && !!config.experimental.serverComponents const disableOptimizedLoading = hasConcurrentFeatures diff --git a/packages/next/pages/_document.tsx b/packages/next/pages/_document.tsx index 309ae6321dcbb..25fe58d8218f5 100644 --- a/packages/next/pages/_document.tsx +++ b/packages/next/pages/_document.tsx @@ -494,11 +494,9 @@ export class Head extends Component< disableOptimizedLoading, optimizeCss, optimizeFonts, - runtime, + hasConcurrentFeatures, } = this.context - const hasConcurrentFeatures = !!runtime - const disableRuntimeJS = unstable_runtimeJS === false const disableJsPreload = unstable_JsPreload === false || !disableOptimizedLoading diff --git a/packages/next/server/dev/hot-reloader.ts b/packages/next/server/dev/hot-reloader.ts index d5e56dbf4f7b4..2dd8d98de3046 100644 --- a/packages/next/server/dev/hot-reloader.ts +++ b/packages/next/server/dev/hot-reloader.ts @@ -154,6 +154,7 @@ export default class HotReloader { private config: NextConfigComplete private runtime?: 'nodejs' | 'edge' private hasServerComponents: boolean + private hasReactRoot: boolean public clientStats: webpack5.Stats | null public serverStats: webpack5.Stats | null private clientError: Error | null = null @@ -197,7 +198,9 @@ export default class HotReloader { this.config = config this.runtime = config.experimental.runtime - this.hasServerComponents = !!config.experimental.serverComponents + this.hasReactRoot = shouldUseReactRoot() + this.hasServerComponents = + this.hasReactRoot && !!config.experimental.serverComponents this.previewProps = previewProps this.rewrites = rewrites this.hotReloaderSpan = trace('hot-reloader', undefined, { @@ -341,8 +344,6 @@ export default class HotReloader { ) ) - const hasReactRoot = shouldUseReactRoot() - return webpackConfigSpan .traceChild('generate-webpack-config') .traceAsyncFn(() => @@ -357,6 +358,7 @@ export default class HotReloader { rewrites: this.rewrites, entrypoints: entrypoints.client, runWebpackSpan: this.hotReloaderSpan, + hasReactRoot: this.hasReactRoot, }), getBaseWebpackConfig(this.dir, { dev: true, @@ -367,9 +369,10 @@ export default class HotReloader { rewrites: this.rewrites, entrypoints: entrypoints.server, runWebpackSpan: this.hotReloaderSpan, + hasReactRoot: this.hasReactRoot, }), // The edge runtime is only supported with React root. - hasReactRoot + this.hasReactRoot ? getBaseWebpackConfig(this.dir, { dev: true, isServer: true, @@ -380,6 +383,7 @@ export default class HotReloader { rewrites: this.rewrites, entrypoints: entrypoints.edgeServer, runWebpackSpan: this.hotReloaderSpan, + hasReactRoot: this.hasReactRoot, }) : null, ].filter(Boolean) as webpack.Configuration[] @@ -418,6 +422,7 @@ export default class HotReloader { this.pagesDir ) ).client, + hasReactRoot: this.hasReactRoot, }) const fallbackCompiler = webpack(fallbackConfig) diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index 66ad197086af5..3850e0e097783 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -61,6 +61,7 @@ import { getMiddlewareRegex } from '../../shared/lib/router/utils/get-middleware import { isCustomErrorPage, isReservedPage } from '../../build/utils' import { NodeNextResponse, NodeNextRequest } from '../base-http/node' import { getPageRuntime, invalidatePageRuntimeCache } from '../../build/entries' +import { shouldUseReactRoot } from '../config' // Load ReactDevOverlay only when needed let ReactDevOverlayImpl: React.FunctionComponent @@ -950,7 +951,7 @@ export default class DevServer extends Server { // TODO: See if this can be moved into hotReloader or removed. await this.hotReloader!.ensurePage('/_error') return await loadDefaultErrorComponents(this.distDir, { - hasConcurrentFeatures: !!this.renderOpts.runtime, + hasConcurrentFeatures: shouldUseReactRoot(), }) } diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 74c40ae65bbba..1ac55928b8d86 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -690,12 +690,17 @@ export default class NextNodeServer extends BaseServer { } protected getServerComponentManifest() { - if (!this.nextConfig.experimental.runtime) return undefined - return require(join( - this.distDir, - 'server', - MIDDLEWARE_FLIGHT_MANIFEST + '.json' - )) + if (!this.nextConfig.experimental.serverComponents) return undefined + try { + return require(join( + this.distDir, + 'server', + MIDDLEWARE_FLIGHT_MANIFEST + '.json' + )) + } catch (err) { + console.error(err) + return undefined + } } protected getCacheFilesystem(): CacheFs { diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index 679fcde4f62be..9bfef1968c90a 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -455,7 +455,7 @@ export async function renderToHTML( AppMod, } = renderOpts - const hasConcurrentFeatures = !!runtime + const hasConcurrentFeatures = reactRoot const OriginalComponent = renderOpts.Component @@ -1241,7 +1241,7 @@ export async function renderToHTML( ) } - if (!runtime && Document.getInitialProps) { + if (!hasConcurrentFeatures && Document.getInitialProps) { const renderPage: RenderPage = ( options: ComponentsEnhancer = {} ): RenderPageResult | Promise => { @@ -1472,6 +1472,7 @@ export async function renderToHTML( optimizeCss: renderOpts.optimizeCss, optimizeFonts: renderOpts.optimizeFonts, runtime, + hasConcurrentFeatures, } const document = ( diff --git a/packages/next/shared/lib/html-context.ts b/packages/next/shared/lib/html-context.ts index 68ecc266d645f..a690bbf149cbe 100644 --- a/packages/next/shared/lib/html-context.ts +++ b/packages/next/shared/lib/html-context.ts @@ -33,6 +33,7 @@ export type HtmlProps = { optimizeCss?: boolean optimizeFonts?: boolean runtime?: 'edge' | 'nodejs' + hasConcurrentFeatures?: boolean } export const HtmlContext = createContext(null as any) diff --git a/test/integration/react-18-invalid-config/index.test.js b/test/integration/react-18-invalid-config/index.test.js index e0096a0b35023..e3a04c07f88b8 100644 --- a/test/integration/react-18-invalid-config/index.test.js +++ b/test/integration/react-18-invalid-config/index.test.js @@ -25,18 +25,18 @@ describe('Invalid react 18 webpack config', () => { ) }) - it('should require `experimental.runtime` for server components', async () => { - writeNextConfig({ - reactRoot: true, - serverComponents: true, - }) - const { stderr } = await nextBuild(appDir, [], { stderr: true }) - nextConfig.restore() - - expect(stderr).toContain( - '`experimental.runtime` is required to be set along with `experimental.serverComponents`.' - ) - }) + // it('should require `experimental.runtime` for server components', async () => { + // writeNextConfig({ + // reactRoot: true, + // serverComponents: true, + // }) + // const { stderr } = await nextBuild(appDir, [], { stderr: true }) + // nextConfig.restore() + + // expect(stderr).toContain( + // '`experimental.runtime` is required to be set along with `experimental.serverComponents`.' + // ) + // }) it('should warn user when not using react 18 and `experimental.reactRoot` is enabled', async () => { const reactDomPackagePah = join(appDir, 'node_modules/react-dom') From 90f4e79e9f9c39ab7362836c70b055162a95402c Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Fri, 11 Mar 2022 23:16:10 +0100 Subject: [PATCH 02/12] add test --- .../switchable-runtime/next.config.js | 9 ++ .../switchable-runtime/package.json | 9 ++ .../switchable-runtime/pages-manifest.json | 9 ++ .../pages/edge-rsc.server.js | 18 ++++ .../switchable-runtime/pages/edge.js | 18 ++++ .../pages/node-rsc.server.js | 18 ++++ .../switchable-runtime/pages/node.js | 18 ++++ .../switchable-runtime/pages/static.js | 14 +++ .../switchable-runtime/utils/runtime.js | 3 + .../switchable-runtime/utils/time.js | 3 + .../test/switchable-runtime.test.js | 101 ++++++++++++++++++ 11 files changed, 220 insertions(+) create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/next.config.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/package.json create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages-manifest.json create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge-rsc.server.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc.server.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/node.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/static.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/utils/runtime.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/utils/time.js create mode 100644 test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/next.config.js b/test/integration/react-streaming-and-server-components/switchable-runtime/next.config.js new file mode 100644 index 0000000000000..7b4ccb839cd64 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/next.config.js @@ -0,0 +1,9 @@ +const withReact18 = require('../../react-18/test/with-react-18') + +module.exports = withReact18({ + reactStrictMode: true, + experimental: { + serverComponents: true, + // runtime: 'edge', + }, +}) diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/package.json b/test/integration/react-streaming-and-server-components/switchable-runtime/package.json new file mode 100644 index 0000000000000..90af0ce830c99 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/package.json @@ -0,0 +1,9 @@ +{ + "private": true, + "scripts": { + "lnext": "node -r ../../react-18/test/require-hook.js ../../../../packages/next/dist/bin/next", + "dev": "yarn lnext dev", + "build": "yarn lnext build", + "start": "yarn lnext start" + } +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages-manifest.json b/test/integration/react-streaming-and-server-components/switchable-runtime/pages-manifest.json new file mode 100644 index 0000000000000..4aa797aeaee30 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages-manifest.json @@ -0,0 +1,9 @@ +{ + "/_app": "pages/_app.js", + "/_error": "pages/_error.js", + "/edge-rsc": "pages/edge-rsc.js", + "/static": "pages/static.js", + "/node-rsc": "pages/node-rsc.js", + "/node": "pages/node.js", + "/edge": "pages/edge.js" +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge-rsc.server.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge-rsc.server.js new file mode 100644 index 0000000000000..83dc8c219e84e --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge-rsc.server.js @@ -0,0 +1,18 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page() { + return ( +
+ This is a SSR RSC page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge.js new file mode 100644 index 0000000000000..c3425c7e64af7 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/edge.js @@ -0,0 +1,18 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page() { + return ( +
+ This is a SSR page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc.server.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc.server.js new file mode 100644 index 0000000000000..f3563039b63bd --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc.server.js @@ -0,0 +1,18 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page() { + return ( +
+ This is a static RSC page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export const config = { + runtime: 'nodejs', +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node.js new file mode 100644 index 0000000000000..bf065da478ba8 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node.js @@ -0,0 +1,18 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page() { + return ( +
+ This is a static page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export const config = { + runtime: 'nodejs', +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/static.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/static.js new file mode 100644 index 0000000000000..e44edfd795232 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/static.js @@ -0,0 +1,14 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page() { + return ( +
+ This is a static page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/utils/runtime.js b/test/integration/react-streaming-and-server-components/switchable-runtime/utils/runtime.js new file mode 100644 index 0000000000000..444f1ee8b498b --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/utils/runtime.js @@ -0,0 +1,3 @@ +export default function getRuntime() { + return process.version ? `Node.js ${process.version}` : 'Edge/Browser' +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/utils/time.js b/test/integration/react-streaming-and-server-components/switchable-runtime/utils/time.js new file mode 100644 index 0000000000000..cf78549b9a7c1 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/utils/time.js @@ -0,0 +1,3 @@ +export default function getTime() { + return Date.now() +} diff --git a/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js new file mode 100644 index 0000000000000..f988267ffccbb --- /dev/null +++ b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js @@ -0,0 +1,101 @@ +/* eslint-env jest */ + +import { join } from 'path' +import { + File, + nextBuild as _nextBuild, + nextStart as _nextStart, +} from 'next-test-utils' + +import { findPort, killApp, renderViaHTTP } from 'next-test-utils' + +const nodeArgs = ['-r', join(__dirname, '../../react-18/test/require-hook.js')] + +const appDir = join(__dirname, '../switchable-runtime') +// const nextConfig = new File(join(appDir, 'next.config.js')) + +async function nextBuild(dir, options) { + return await _nextBuild(dir, [], { + ...options, + stdout: true, + stderr: true, + nodeArgs, + }) +} + +async function nextStart(dir, port) { + return await _nextStart(dir, port, { + stdout: true, + stderr: true, + nodeArgs, + }) +} + +async function testRoute(appPort, url, { isStatic, isEdge }) { + const html1 = await renderViaHTTP(appPort, url) + const renderedAt1 = +html1.match(/Time: (\d+)/)[1] + expect(html1).toContain(`Runtime: ${isEdge ? 'Edge' : 'Node.js'}`) + + const html2 = await renderViaHTTP(appPort, url) + const renderedAt2 = +html2.match(/Time: (\d+)/)[1] + expect(html2).toContain(`Runtime: ${isEdge ? 'Edge' : 'Node.js'}`) + + if (isStatic) { + // Should not be re-rendered, some timestamp should be returned. + expect(renderedAt1).toBe(renderedAt2) + } else { + // Should be re-rendered. + expect(renderedAt1).toBeLessThan(renderedAt2) + } +} + +describe('Without global runtime configuration', () => { + const context = { appDir } + + beforeAll(async () => { + // error500Page.write(page500) + context.appPort = await findPort() + const { stderr } = await nextBuild(context.appDir) + context.stderr = stderr + context.server = await nextStart(context.appDir, context.appPort) + }) + afterAll(async () => { + // error500Page.delete() + await killApp(context.server) + }) + + it('should build /static as a static page with the nodejs runtime', async () => { + await testRoute(context.appPort, '/static', { + isStatic: true, + isEdge: false, + }) + }) + + it('should build /node as a static page with the nodejs runtime', async () => { + await testRoute(context.appPort, '/node', { + isStatic: true, + isEdge: false, + }) + }) + + it('should build /node-rsc as a static page with the nodejs runtime', async () => { + await testRoute(context.appPort, '/node-rsc', { + isStatic: true, + isEdge: false, + }) + }) + + it('should build /edge as a dynamic page with the edge runtime', async () => { + await testRoute(context.appPort, '/edge', { + isStatic: false, + isEdge: true, + }) + }) + + it('should build /edge-rsc as a dynamic page with the edge runtime', async () => { + await testRoute(context.appPort, '/edge-rsc', { + isStatic: false, + isEdge: true, + }) + }) +}) From ff5c71a691f0a9714cd07c3636a29f66dbd71db5 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Fri, 11 Mar 2022 23:37:52 +0100 Subject: [PATCH 03/12] add more tests --- .../pages/node-rsc-ssg.server.js | 26 +++++++++++++++++ .../pages/node-rsc-ssr.server.js | 26 +++++++++++++++++ .../switchable-runtime/pages/node-ssg.js | 26 +++++++++++++++++ .../switchable-runtime/pages/node-ssr.js | 26 +++++++++++++++++ .../test/switchable-runtime.test.js | 28 +++++++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssg.server.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssr.server.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssg.js create mode 100644 test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssr.js diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssg.server.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssg.server.js new file mode 100644 index 0000000000000..362e634644eb2 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssg.server.js @@ -0,0 +1,26 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page({ type }) { + return ( +
+ This is a {type} RSC page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export function getStaticProps() { + return { + props: { + type: 'SSG', + }, + } +} + +export const config = { + runtime: 'nodejs', +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssr.server.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssr.server.js new file mode 100644 index 0000000000000..1b8b01526a3ce --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-rsc-ssr.server.js @@ -0,0 +1,26 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page({ type }) { + return ( +
+ This is a {type} RSC page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export function getServerSideProps() { + return { + props: { + type: 'SSR', + }, + } +} + +export const config = { + runtime: 'nodejs', +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssg.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssg.js new file mode 100644 index 0000000000000..d555009acfcdb --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssg.js @@ -0,0 +1,26 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page({ type }) { + return ( +
+ This is a {type} page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export function getStaticProps() { + return { + props: { + type: 'SSG', + }, + } +} + +export const config = { + runtime: 'nodejs', +} diff --git a/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssr.js b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssr.js new file mode 100644 index 0000000000000..e58276b47a763 --- /dev/null +++ b/test/integration/react-streaming-and-server-components/switchable-runtime/pages/node-ssr.js @@ -0,0 +1,26 @@ +import getRuntime from '../utils/runtime' +import getTime from '../utils/time' + +export default function Page({ type }) { + return ( +
+ This is a {type} page. +
+ {'Runtime: ' + getRuntime()} +
+ {'Time: ' + getTime()} +
+ ) +} + +export function getServerSideProps() { + return { + props: { + type: 'SSR', + }, + } +} + +export const config = { + runtime: 'nodejs', +} diff --git a/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js index f988267ffccbb..249d149d4846b 100644 --- a/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js +++ b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js @@ -78,6 +78,20 @@ describe('Without global runtime configuration', () => { }) }) + it('should build /node-ssr as a dynamic page with the nodejs runtime', async () => { + await testRoute(context.appPort, '/node-ssr', { + isStatic: false, + isEdge: false, + }) + }) + + it('should build /node-ssg as a static page with the nodejs runtime', async () => { + await testRoute(context.appPort, '/node-ssg', { + isStatic: true, + isEdge: false, + }) + }) + it('should build /node-rsc as a static page with the nodejs runtime', async () => { await testRoute(context.appPort, '/node-rsc', { isStatic: true, @@ -85,6 +99,20 @@ describe('Without global runtime configuration', () => { }) }) + it('should build /node-rsc-ssr as a dynamic page with the nodejs runtime', async () => { + await testRoute(context.appPort, '/node-rsc-ssr', { + isStatic: false, + isEdge: false, + }) + }) + + it('should build /node-rsc-ssg as a static page with the nodejs runtime', async () => { + await testRoute(context.appPort, '/node-rsc-ssg', { + isStatic: true, + isEdge: false, + }) + }) + it('should build /edge as a dynamic page with the edge runtime', async () => { await testRoute(context.appPort, '/edge', { isStatic: false, From 373747a7ae44614ff03bd50eaecd79f0059520e0 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Sat, 12 Mar 2022 00:00:25 +0100 Subject: [PATCH 04/12] fix linter errors --- packages/next/build/index.ts | 17 +++++++++-------- packages/next/server/dev/next-dev-server.ts | 1 - .../react-18-invalid-config/index.test.js | 13 ------------- .../test/switchable-runtime.test.js | 2 +- 4 files changed, 10 insertions(+), 23 deletions(-) diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 3b47344812610..3e0584d68b439 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -960,15 +960,16 @@ export default async function build( let ssgPageRoutes: string[] | null = null let isMiddlewareRoute = !!page.match(MIDDLEWARE_ROUTE) - const pagePath = pagePaths.find((path) => - path.startsWith(actualPage + '.') + const pagePath = pagePaths.find((_path) => + _path.startsWith(actualPage + '.') ) - const pageRuntime = pagePath - ? await getPageRuntime( - join(pagesDir, pagePath), - config.experimental.runtime - ) - : null + const pageRuntime = + hasConcurrentFeatures && pagePath + ? await getPageRuntime( + join(pagesDir, pagePath), + config.experimental.runtime + ) + : null if ( !isMiddlewareRoute && diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index cd274d313d8c7..2a18039e6481d 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -62,7 +62,6 @@ import { getMiddlewareRegex } from '../../shared/lib/router/utils/get-middleware import { isCustomErrorPage, isReservedPage } from '../../build/utils' import { NodeNextResponse, NodeNextRequest } from '../base-http/node' import { getPageRuntime, invalidatePageRuntimeCache } from '../../build/entries' -import { shouldUseReactRoot } from '../config' // Load ReactDevOverlay only when needed let ReactDevOverlayImpl: React.FunctionComponent diff --git a/test/integration/react-18-invalid-config/index.test.js b/test/integration/react-18-invalid-config/index.test.js index e3a04c07f88b8..9372f0f199f4d 100644 --- a/test/integration/react-18-invalid-config/index.test.js +++ b/test/integration/react-18-invalid-config/index.test.js @@ -25,19 +25,6 @@ describe('Invalid react 18 webpack config', () => { ) }) - // it('should require `experimental.runtime` for server components', async () => { - // writeNextConfig({ - // reactRoot: true, - // serverComponents: true, - // }) - // const { stderr } = await nextBuild(appDir, [], { stderr: true }) - // nextConfig.restore() - - // expect(stderr).toContain( - // '`experimental.runtime` is required to be set along with `experimental.serverComponents`.' - // ) - // }) - it('should warn user when not using react 18 and `experimental.reactRoot` is enabled', async () => { const reactDomPackagePah = join(appDir, 'node_modules/react-dom') await fs.mkdirp(reactDomPackagePah) diff --git a/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js index 249d149d4846b..ed9a29d3cadf0 100644 --- a/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js +++ b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js @@ -2,7 +2,7 @@ import { join } from 'path' import { - File, + // File, nextBuild as _nextBuild, nextStart as _nextStart, } from 'next-test-utils' From 5216611300b1eb592345568b306cf4babd500efc Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Mon, 14 Mar 2022 22:51:23 +0100 Subject: [PATCH 05/12] fix missing server components --- packages/next/export/worker.ts | 11 +++++++++-- packages/next/server/load-components.ts | 18 +++++++++++++----- packages/next/server/render.tsx | 6 +++--- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/next/export/worker.ts b/packages/next/export/worker.ts index f2e6dbb64f133..3679b28eebd1d 100644 --- a/packages/next/export/worker.ts +++ b/packages/next/export/worker.ts @@ -59,6 +59,7 @@ interface ExportPageInput { disableOptimizedLoading: any parentSpanId: any httpAgentOptions: NextConfigComplete['httpAgentOptions'] + serverComponents?: boolean } interface ExportPageResults { @@ -106,6 +107,7 @@ export default async function exportPage({ optimizeCss, disableOptimizedLoading, httpAgentOptions, + serverComponents, }: ExportPageInput): Promise { setHttpAgentOptions(httpAgentOptions) const exportPageSpan = trace('export-page-worker', parentSpanId) @@ -260,7 +262,7 @@ export default async function exportPage({ getServerSideProps, getStaticProps, pageConfig, - } = await loadComponents(distDir, page, serverless) + } = await loadComponents(distDir, page, serverless, serverComponents) const ampState = { ampFirst: pageConfig?.amp === true, hasQuery: Boolean(query.amp), @@ -321,7 +323,12 @@ export default async function exportPage({ throw new Error(`Failed to render serverless page`) } } else { - const components = await loadComponents(distDir, page, serverless) + const components = await loadComponents( + distDir, + page, + serverless, + serverComponents + ) const ampState = { ampFirst: components.pageConfig?.amp === true, hasQuery: Boolean(query.amp), diff --git a/packages/next/server/load-components.ts b/packages/next/server/load-components.ts index ae247d9ea66fd..0f45b7292e0b0 100644 --- a/packages/next/server/load-components.ts +++ b/packages/next/server/load-components.ts @@ -6,6 +6,7 @@ import type { import { BUILD_MANIFEST, REACT_LOADABLE_MANIFEST, + MIDDLEWARE_FLIGHT_MANIFEST, } from '../shared/lib/constants' import { join } from 'path' import { requirePage } from './require' @@ -30,6 +31,7 @@ export type LoadComponentsReturnType = { pageConfig: PageConfig buildManifest: BuildManifest reactLoadableManifest: ReactLoadableManifest + serverComponentManifest: any | null Document: DocumentType App: AppType getStaticProps?: GetStaticProps @@ -61,7 +63,8 @@ export async function loadDefaultErrorComponents(distDir: string) { export async function loadComponents( distDir: string, pathname: string, - serverless: boolean + serverless: boolean, + serverComponents?: boolean ): Promise { if (serverless) { const ComponentMod = await requirePage(pathname, distDir, serverless) @@ -102,10 +105,14 @@ export async function loadComponents( requirePage(pathname, distDir, serverless), ]) - const [buildManifest, reactLoadableManifest] = await Promise.all([ - require(join(distDir, BUILD_MANIFEST)), - require(join(distDir, REACT_LOADABLE_MANIFEST)), - ]) + const [buildManifest, reactLoadableManifest, serverComponentManifest] = + await Promise.all([ + require(join(distDir, BUILD_MANIFEST)), + require(join(distDir, REACT_LOADABLE_MANIFEST)), + serverComponents + ? require(join(distDir, 'server', MIDDLEWARE_FLIGHT_MANIFEST + '.json')) + : null, + ]) const Component = interopDefault(ComponentMod) const Document = interopDefault(DocumentMod) @@ -125,5 +132,6 @@ export async function loadComponents( getServerSideProps, getStaticProps, getStaticPaths, + serverComponentManifest, } } diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index 8db0b13d1a10e..e1b712bee14aa 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -450,7 +450,7 @@ export async function renderToHTML( supportsDynamicHTML, images, reactRoot, - runtime, + runtime: globalRuntime, ComponentMod, AppMod, } = renderOpts @@ -1243,7 +1243,7 @@ export async function renderToHTML( | typeof Document | undefined - if (runtime === 'edge' && Document.getInitialProps) { + if (process.browser && Document.getInitialProps) { // In the Edge runtime, `Document.getInitialProps` isn't supported. // We throw an error here if it's customized. if (!builtinDocument) { @@ -1489,7 +1489,7 @@ export async function renderToHTML( optimizeCss: renderOpts.optimizeCss, optimizeFonts: renderOpts.optimizeFonts, nextScriptWorkers: renderOpts.nextScriptWorkers, - runtime, + runtime: globalRuntime, hasConcurrentFeatures, } From 63d9a23736e23405d0e2ec1c159f3e38f1f8efb3 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Mon, 14 Mar 2022 23:16:49 +0100 Subject: [PATCH 06/12] fix tests --- packages/next/export/index.ts | 1 + .../app/pages/err/render.js | 4 ++++ .../app/pages/err/suspense.js | 4 ++++ .../app/pages/next-api/image.server.js | 4 ++++ .../app/pages/next-api/link.server.js | 4 ++++ .../app/pages/partial-hydration.server.js | 4 ++++ .../app/pages/routes/[dynamic].server.js | 4 ++++ .../app/pages/streaming-rsc.server.js | 4 ++++ .../app/pages/streaming.js | 4 ++++ .../unsupported-native-module/next.config.js | 1 - .../unsupported-native-module/pages/index.js | 4 ++++ 11 files changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/next/export/index.ts b/packages/next/export/index.ts index 937c01ab089cf..df995262048ee 100644 --- a/packages/next/export/index.ts +++ b/packages/next/export/index.ts @@ -588,6 +588,7 @@ export default async function exportApp( nextConfig.experimental.disableOptimizedLoading, parentSpanId: pageExportSpan.id, httpAgentOptions: nextConfig.httpAgentOptions, + serverComponents: nextConfig.experimental.serverComponents, }) for (const validation of result.ampValidations || []) { diff --git a/test/integration/react-streaming-and-server-components/app/pages/err/render.js b/test/integration/react-streaming-and-server-components/app/pages/err/render.js index 0c6ec0bd1baed..7d9d321f7cb0a 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/err/render.js +++ b/test/integration/react-streaming-and-server-components/app/pages/err/render.js @@ -5,3 +5,7 @@ export default function MyError() { throw new Error('oops') } } + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/app/pages/err/suspense.js b/test/integration/react-streaming-and-server-components/app/pages/err/suspense.js index e23ccd094bbab..05f85b9f4b16f 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/err/suspense.js +++ b/test/integration/react-streaming-and-server-components/app/pages/err/suspense.js @@ -18,3 +18,7 @@ export default function page() { ) } + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/app/pages/next-api/image.server.js b/test/integration/react-streaming-and-server-components/app/pages/next-api/image.server.js index 0083c3b9d4ccb..96c50ace36a55 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/next-api/image.server.js +++ b/test/integration/react-streaming-and-server-components/app/pages/next-api/image.server.js @@ -7,3 +7,7 @@ const Page = () => { } export default Page + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/app/pages/next-api/link.server.js b/test/integration/react-streaming-and-server-components/app/pages/next-api/link.server.js index a0e988f015f2c..c5fdc1f1d40fc 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/next-api/link.server.js +++ b/test/integration/react-streaming-and-server-components/app/pages/next-api/link.server.js @@ -15,3 +15,7 @@ export default function LinkPage({ router }) { ) } + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/app/pages/partial-hydration.server.js b/test/integration/react-streaming-and-server-components/app/pages/partial-hydration.server.js index c3740b8719fed..8604f3bdcb726 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/partial-hydration.server.js +++ b/test/integration/react-streaming-and-server-components/app/pages/partial-hydration.server.js @@ -40,3 +40,7 @@ export default function () { ) } + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/app/pages/routes/[dynamic].server.js b/test/integration/react-streaming-and-server-components/app/pages/routes/[dynamic].server.js index 288d6165f9990..27c7c0bddf028 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/routes/[dynamic].server.js +++ b/test/integration/react-streaming-and-server-components/app/pages/routes/[dynamic].server.js @@ -1,3 +1,7 @@ export default function Pid({ router }) { return
{`query: ${router.query.dynamic}`}
} + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/app/pages/streaming-rsc.server.js b/test/integration/react-streaming-and-server-components/app/pages/streaming-rsc.server.js index ac58f5e9e2c38..70aaf4ced70ef 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/streaming-rsc.server.js +++ b/test/integration/react-streaming-and-server-components/app/pages/streaming-rsc.server.js @@ -21,3 +21,7 @@ export default function Page() { ) } + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/app/pages/streaming.js b/test/integration/react-streaming-and-server-components/app/pages/streaming.js index ac58f5e9e2c38..70aaf4ced70ef 100644 --- a/test/integration/react-streaming-and-server-components/app/pages/streaming.js +++ b/test/integration/react-streaming-and-server-components/app/pages/streaming.js @@ -21,3 +21,7 @@ export default function Page() { ) } + +export const config = { + runtime: 'edge', +} diff --git a/test/integration/react-streaming-and-server-components/unsupported-native-module/next.config.js b/test/integration/react-streaming-and-server-components/unsupported-native-module/next.config.js index 4783ccbdadb78..deb87bcba88d7 100644 --- a/test/integration/react-streaming-and-server-components/unsupported-native-module/next.config.js +++ b/test/integration/react-streaming-and-server-components/unsupported-native-module/next.config.js @@ -3,7 +3,6 @@ const withReact18 = require('../../react-18/test/with-react-18') module.exports = withReact18({ experimental: { reactRoot: true, - runtime: 'edge', serverComponents: true, }, }) diff --git a/test/integration/react-streaming-and-server-components/unsupported-native-module/pages/index.js b/test/integration/react-streaming-and-server-components/unsupported-native-module/pages/index.js index 31f0f204a9d3b..8371b4c194f7d 100644 --- a/test/integration/react-streaming-and-server-components/unsupported-native-module/pages/index.js +++ b/test/integration/react-streaming-and-server-components/unsupported-native-module/pages/index.js @@ -8,3 +8,7 @@ export default function Index() { console.log(EOF) return 'Access Node.js native module dns' } + +export const config = { + runtime: 'edge', +} From 894c95e1ed96a123a9eab9dcb7ad1ac732228d10 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Mon, 14 Mar 2022 23:23:30 +0100 Subject: [PATCH 07/12] fix type errors --- packages/next/server/load-components.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/server/load-components.ts b/packages/next/server/load-components.ts index 0f45b7292e0b0..361f0183899d5 100644 --- a/packages/next/server/load-components.ts +++ b/packages/next/server/load-components.ts @@ -31,7 +31,7 @@ export type LoadComponentsReturnType = { pageConfig: PageConfig buildManifest: BuildManifest reactLoadableManifest: ReactLoadableManifest - serverComponentManifest: any | null + serverComponentManifest?: any | null Document: DocumentType App: AppType getStaticProps?: GetStaticProps From db560447e5566a95d8ecb2957d270ebf76b5788d Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 15 Mar 2022 20:03:20 +0100 Subject: [PATCH 08/12] fix test --- packages/next/server/render.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/next/server/render.tsx b/packages/next/server/render.tsx index e1b712bee14aa..190cfadc6b279 100644 --- a/packages/next/server/render.tsx +++ b/packages/next/server/render.tsx @@ -464,7 +464,7 @@ export async function renderToHTML( const isServerComponent = !!serverComponentManifest && hasConcurrentFeatures && - ComponentMod.__next_rsc__ + !!ComponentMod.__next_rsc__ let Component: React.ComponentType<{}> | ((props: any) => JSX.Element) = renderOpts.Component @@ -1329,7 +1329,8 @@ export async function renderToHTML( ) : ( - {renderOpts.serverComponents && AppMod.__next_rsc__ ? ( + {isServerComponent && AppMod.__next_rsc__ ? ( + // _app.server.js is used. ) : ( @@ -1361,7 +1362,6 @@ export async function renderToHTML( ), generateStaticHTML: true, }) - const flushed = await streamToString(flushEffectStream) return flushed } From 2af08047e1d62b06ec3a6e58663f39d609cd0a4f Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 15 Mar 2022 21:46:04 +0100 Subject: [PATCH 09/12] fix tests --- .../react-18/app/pages/suspense/no-preload.js | 3 ++- test/integration/react-18/test/basics.js | 2 +- test/integration/react-18/test/blocking.js | 17 +++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/test/integration/react-18/app/pages/suspense/no-preload.js b/test/integration/react-18/app/pages/suspense/no-preload.js index aaf54e244118f..8ae8c7c599f2e 100644 --- a/test/integration/react-18/app/pages/suspense/no-preload.js +++ b/test/integration/react-18/app/pages/suspense/no-preload.js @@ -2,6 +2,7 @@ import { Suspense } from 'react' import dynamic from 'next/dynamic' const Bar = dynamic(() => import('../../components/bar'), { + ssr: false, suspense: true, // Explicitly declare loaded modules. // For suspense cases, they'll be ignored. @@ -14,7 +15,7 @@ const Bar = dynamic(() => import('../../components/bar'), { export default function NoPreload() { return ( - + ) diff --git a/test/integration/react-18/test/basics.js b/test/integration/react-18/test/basics.js index debbad85a56b5..bc63d2ad4f0f5 100644 --- a/test/integration/react-18/test/basics.js +++ b/test/integration/react-18/test/basics.js @@ -31,7 +31,7 @@ export default (context) => { const nextData = JSON.parse($('#__NEXT_DATA__').text()) const content = $('#__next').text() // is suspended - expect(content).toBe('rab') + expect(content).toBe('fallback') expect(nextData.dynamicIds).toBeUndefined() }) diff --git a/test/integration/react-18/test/blocking.js b/test/integration/react-18/test/blocking.js index c4feeb2e8a301..32714e24e62b5 100644 --- a/test/integration/react-18/test/blocking.js +++ b/test/integration/react-18/test/blocking.js @@ -8,18 +8,19 @@ export default (context, render) => { return cheerio.load(html) } - it('should render fallback on server side if suspense without preload', async () => { + it('should render fallback on server side if suspense without ssr', async () => { const $ = await get$('/suspense/no-preload') const nextData = JSON.parse($('#__NEXT_DATA__').text()) const content = $('#__next').text() - expect(content).toBe('rab') + expect(content).toBe('fallback') expect(nextData.dynamicIds).toBeUndefined() }) - it('should render fallback on server side if suspended on server with preload', async () => { - const $ = await get$('/suspense/thrown') - const html = $('body').html() - expect(html).toContain('loading') - expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined() - }) + // Testing the same thing as above. + // it('should render import fallback on server side if suspended without ssr', async () => { + // const $ = await get$('/suspense/thrown') + // const html = $('body').html() + // expect(html).toContain('loading') + // expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined() + // }) } From 9d59dcc1957f4e7b8bed6e85a7cb746aa39c5673 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Tue, 15 Mar 2022 21:56:51 +0100 Subject: [PATCH 10/12] use skip test --- test/integration/react-18/test/blocking.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/integration/react-18/test/blocking.js b/test/integration/react-18/test/blocking.js index 32714e24e62b5..0db4aacd6cf97 100644 --- a/test/integration/react-18/test/blocking.js +++ b/test/integration/react-18/test/blocking.js @@ -17,10 +17,10 @@ export default (context, render) => { }) // Testing the same thing as above. - // it('should render import fallback on server side if suspended without ssr', async () => { - // const $ = await get$('/suspense/thrown') - // const html = $('body').html() - // expect(html).toContain('loading') - // expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined() - // }) + it.skip('should render import fallback on server side if suspended without ssr', async () => { + const $ = await get$('/suspense/thrown') + const html = $('body').html() + expect(html).toContain('loading') + expect(JSON.parse($('#__NEXT_DATA__').text()).dynamicIds).toBeUndefined() + }) } From 4ecc43a77236e837901c63772e34c5fc76f29904 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 16 Mar 2022 11:33:20 +0100 Subject: [PATCH 11/12] remove comments --- .../test/switchable-runtime.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js index ed9a29d3cadf0..62ebdcadf4264 100644 --- a/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js +++ b/test/integration/react-streaming-and-server-components/test/switchable-runtime.test.js @@ -53,14 +53,12 @@ describe('Without global runtime configuration', () => { const context = { appDir } beforeAll(async () => { - // error500Page.write(page500) context.appPort = await findPort() const { stderr } = await nextBuild(context.appDir) context.stderr = stderr context.server = await nextStart(context.appDir, context.appPort) }) afterAll(async () => { - // error500Page.delete() await killApp(context.server) }) From 2a462475c74a88b70075d97098a8fdb17a875a4e Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Wed, 16 Mar 2022 12:46:38 +0100 Subject: [PATCH 12/12] remove try-catch wrapper for loading flight manifest --- packages/next/server/next-server.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 32cde739af11f..2455112a313d7 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -694,16 +694,11 @@ export default class NextNodeServer extends BaseServer { protected getServerComponentManifest() { if (!this.nextConfig.experimental.serverComponents) return undefined - try { - return require(join( - this.distDir, - 'server', - MIDDLEWARE_FLIGHT_MANIFEST + '.json' - )) - } catch (err) { - console.error(err) - return undefined - } + return require(join( + this.distDir, + 'server', + MIDDLEWARE_FLIGHT_MANIFEST + '.json' + )) } protected getCacheFilesystem(): CacheFs {