diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 427565463690ff..eab85535f3556a 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1450,7 +1450,8 @@ export default async function getBaseWebpackConfig( resourceRegExp: /react-is/, contextRegExp: /next[\\/]dist[\\/]/, }), - isServerless && isServer && !webServerRuntime && new ServerlessPlugin(), + ((isServerless && isServer) || webServerRuntime) && + new ServerlessPlugin(), isServer && !webServerRuntime && new PagesManifestPlugin({ serverless: isLikeServerless, dev }), diff --git a/packages/next/build/webpack/config/blocks/base.ts b/packages/next/build/webpack/config/blocks/base.ts index 9c8799633391f5..34ee68b412520a 100644 --- a/packages/next/build/webpack/config/blocks/base.ts +++ b/packages/next/build/webpack/config/blocks/base.ts @@ -14,7 +14,11 @@ export const base = curry(function base( : 'client' // @ts-ignore TODO webpack 5 typings - config.target = !ctx.targetWeb ? 'node12.22' : ['web', 'es5'] + config.target = !ctx.targetWeb + ? 'node12.22' + : ctx.webServerRuntime + ? ['web', 'es6'] + : ['web', 'es5'] // https://webpack.js.org/configuration/devtool/#development if (ctx.isDevelopment) { diff --git a/packages/next/build/webpack/loaders/next-flight-client-loader.ts b/packages/next/build/webpack/loaders/next-flight-client-loader.ts index da75ead76bee02..8dc2ea1595db9b 100644 --- a/packages/next/build/webpack/loaders/next-flight-client-loader.ts +++ b/packages/next/build/webpack/loaders/next-flight-client-loader.ts @@ -81,7 +81,7 @@ async function parseExportNamesInto( loadModule: TransformSourceFunction ): Promise { const { body } = acorn.parse(transformedSource, { - ecmaVersion: 2019, + ecmaVersion: 11, sourceType: 'module', }) as any for (let i = 0; i < body.length; i++) { diff --git a/packages/next/build/webpack/loaders/next-flight-server-loader.ts b/packages/next/build/webpack/loaders/next-flight-server-loader.ts index c50d63bc516314..9e0cfb7cc4f965 100644 --- a/packages/next/build/webpack/loaders/next-flight-server-loader.ts +++ b/packages/next/build/webpack/loaders/next-flight-server-loader.ts @@ -28,7 +28,7 @@ async function parseImportsInfo( pageExtensions: string[] ): Promise { const { body } = acorn.parse(source, { - ecmaVersion: 2019, + ecmaVersion: 11, sourceType: 'module', }) as any diff --git a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts index f3d2cb03700578..1f367ac3eadebd 100644 --- a/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts +++ b/packages/next/build/webpack/loaders/next-middleware-ssr-loader/index.ts @@ -51,7 +51,7 @@ export default async function middlewareRSCLoader(this: any) { const buildManifest = self.__BUILD_MANIFEST const reactLoadableManifest = self.__REACT_LOADABLE_MANIFEST - const rscManifest = self._middleware_rsc_manifest + const rscManifest = self.__RSC_MANIFEST if (typeof Page !== 'function') { throw new Error('Your page must export a \`default\` component') diff --git a/packages/next/build/webpack/plugins/flight-manifest-plugin.ts b/packages/next/build/webpack/plugins/flight-manifest-plugin.ts index d44a4540d3c603..1a525c3fed2533 100644 --- a/packages/next/build/webpack/plugins/flight-manifest-plugin.ts +++ b/packages/next/build/webpack/plugins/flight-manifest-plugin.ts @@ -120,9 +120,7 @@ export class FlightManifestPlugin { }) }) - const output = - `self._middleware_rsc_manifest=(typeof _ENTRIES === "undefined"?{}:_ENTRIES)._middleware_rsc_manifest=` + - JSON.stringify(json) + const output = `self.__RSC_MANIFEST=` + JSON.stringify(json) assets[`server/${MIDDLEWARE_FLIGHT_MANIFEST}.js`] = new sources.RawSource( output ) diff --git a/packages/next/server/web/sandbox/sandbox.ts b/packages/next/server/web/sandbox/sandbox.ts index 8e02e9ec81441d..a6e3688f236c46 100644 --- a/packages/next/server/web/sandbox/sandbox.ts +++ b/packages/next/server/web/sandbox/sandbox.ts @@ -130,13 +130,10 @@ export async function run(params: { const entryPoint = cache.context._ENTRIES[`middleware_${params.name}`] if (params.ssr) { - const rscManifest = cache.context._ENTRIES._middleware_rsc_manifest cache = undefined - - if (rscManifest && entryPoint) { + if (entryPoint) { return entryPoint.default({ request: params.request, - rscManifest, }) } } diff --git a/test/integration/react-streaming-and-server-components/app/pages/dynamic-imports.js b/test/integration/react-streaming-and-server-components/app/pages/dynamic-imports.js new file mode 100644 index 00000000000000..60e8bf7fe0c16b --- /dev/null +++ b/test/integration/react-streaming-and-server-components/app/pages/dynamic-imports.js @@ -0,0 +1,13 @@ +import { lazy, Suspense } from 'react' + +const Foo = lazy(() => import('../components/foo.client')) + +export default function Page() { + return ( +
+ + + +
+ ) +} diff --git a/test/integration/react-streaming-and-server-components/test/index.test.js b/test/integration/react-streaming-and-server-components/test/index.test.js index daf517841975eb..613c90d350d5e7 100644 --- a/test/integration/react-streaming-and-server-components/test/index.test.js +++ b/test/integration/react-streaming-and-server-components/test/index.test.js @@ -3,6 +3,7 @@ import cheerio from 'cheerio' import { join } from 'path' import fs from 'fs-extra' +import webdriver from 'next-webdriver' import { File, @@ -140,6 +141,12 @@ describe('concurrentFeatures - prod', () => { expect(content.clientInfo).toContainEqual(item) } }) + + it('should support React.lazy and dynamic imports', async () => { + const html = await renderViaHTTP(context.appPort, '/dynamic-imports') + expect(html).toContain('foo.client') + }) + runBasicTests(context) }) @@ -153,6 +160,16 @@ describe('concurrentFeatures - dev', () => { afterAll(async () => { await killApp(context.server) }) + + it('should support React.lazy and dynamic imports', async () => { + const html = await renderViaHTTP(context.appPort, '/dynamic-imports') + expect(html).toContain('loading...') + + const browser = await webdriver(context.appPort, '/dynamic-imports') + const content = await browser.eval(`window.document.body.innerText`) + expect(content).toMatchInlineSnapshot('"foo.client"') + }) + runBasicTests(context) })