From 5e6b008b561caf2710ab7be63320a3d549474a5b Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 6 Oct 2022 12:51:41 -0400 Subject: [PATCH 01/13] Fix docs for next/image unconfigured hosts (#41223) Fix docs for next/image unconfigured hosts to mention `remotePatterns`. --- errors/next-image-unconfigured-host.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/errors/next-image-unconfigured-host.md b/errors/next-image-unconfigured-host.md index e69525ad03d2b..0af043bc5499b 100644 --- a/errors/next-image-unconfigured-host.md +++ b/errors/next-image-unconfigured-host.md @@ -2,11 +2,29 @@ #### Why This Error Occurred -On one of your pages that leverages the `next/image` component, you passed a `src` value that uses a hostname in the URL that isn't defined in the `images.domains` config in `next.config.js`. +One of your pages that leverages the `next/image` component, passed a `src` value that uses a hostname in the URL that isn't defined in the `images.remotePatterns` or `images.domains` in `next.config.js`. #### Possible Ways to Fix It -Add the hostname of your URL to the `images.domains` config in `next.config.js`: +Add the protocol, hostname, port, and pathname to the `images.remotePatterns` config in `next.config.js`: + +```js +// next.config.js +module.exports = { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'example.com', + port: '', + pathname: '/account123/**', + }, + ], + }, +} +``` + +If you are using an older version of Next.js prior to 12.3.0, you can use `images.domains` instead: ```js // next.config.js From 24b600303f2e8074c32b79d9b799ade85772d75e Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 6 Oct 2022 20:27:24 +0200 Subject: [PATCH 02/13] Do not bundle `react-dom` in the SSR build (#41227) Currently `react-dom` isn't handled as an external dependency in SSR, unlike `react`. This means that the ReactDOM imported by client components isn't the same instance as the ReactDOM that does SSR. This PR also upgrades React experimental to the latest version. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) --- package.json | 4 ++-- packages/next/build/webpack-config.ts | 2 +- pnpm-lock.yaml | 29 +++++++++++++++------------ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 1ee637d1850ef..a714f570af829 100644 --- a/package.json +++ b/package.json @@ -183,8 +183,8 @@ "react-17": "npm:react@17.0.2", "react-dom": "18.2.0", "react-dom-17": "npm:react-dom@17.0.2", - "react-dom-exp": "npm:react-dom@0.0.0-experimental-65b3449c8-20221005", - "react-exp": "npm:react@0.0.0-experimental-65b3449c8-20221005", + "react-dom-exp": "npm:react-dom@0.0.0-experimental-e40893d09-20221005", + "react-exp": "npm:react@0.0.0-experimental-e40893d09-20221005", "react-ssr-prepass": "1.0.8", "react-virtualized": "9.22.3", "relay-compiler": "13.0.2", diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index b6f7be7f3d1e4..0293a1998ba4d 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1049,7 +1049,7 @@ export default async function getBaseWebpackConfig( // Absolute requires (require('/foo')) are extremely uncommon, but // also have no need for customization as they're already resolved. if (!isLocal) { - if (/^(?:next$|react(?:$|\/))/.test(request)) { + if (/^(?:next$|react(?:$|\/)|react-dom(?:$|\/))/.test(request)) { return `commonjs ${request}` } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8f5b52a68ea60..caf19ef7c2d7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -144,8 +144,8 @@ importers: react-17: npm:react@17.0.2 react-dom: 18.2.0 react-dom-17: npm:react-dom@17.0.2 - react-dom-exp: npm:react-dom@0.0.0-experimental-65b3449c8-20221005 - react-exp: npm:react@0.0.0-experimental-65b3449c8-20221005 + react-dom-exp: npm:react-dom@0.0.0-experimental-e40893d09-20221005 + react-exp: npm:react@0.0.0-experimental-e40893d09-20221005 react-ssr-prepass: 1.0.8 react-virtualized: 9.22.3 relay-compiler: 13.0.2 @@ -303,8 +303,8 @@ importers: react-17: /react/17.0.2 react-dom: 18.2.0_react@18.2.0 react-dom-17: /react-dom/17.0.2_react@18.2.0 - react-dom-exp: /react-dom/0.0.0-experimental-65b3449c8-20221005_react@18.2.0 - react-exp: /react/0.0.0-experimental-65b3449c8-20221005 + react-dom-exp: /react-dom/0.0.0-experimental-e40893d09-20221005_react@18.2.0 + react-exp: /react/0.0.0-experimental-e40893d09-20221005 react-ssr-prepass: 1.0.8_qncsgtzehe3fgiqp6tr7lwq6fm react-virtualized: 9.22.3_biqbaboplfbrettd7655fr4n2y relay-compiler: 13.0.2 @@ -25221,17 +25221,17 @@ packages: strip-json-comments: 2.0.1 dev: true - /react-dom/0.0.0-experimental-65b3449c8-20221005_react@18.2.0: + /react-dom/0.0.0-experimental-e40893d09-20221005_react@18.2.0: resolution: { - integrity: sha512-EwMQkdTwP8NNAgtZS6Z+Pia3BJ5WetngkNtqZKtah8sGw5wx+1FjvEKzYuFCxwAzJIIoyCyoDbvHZYmi/XSgJw==, + integrity: sha512-Zw1FWTy9XEiiLU1KCYFpLUs1KAMiNfWW1Clz0DCX1diGLeSfBhp2Jd3/7+v8U9SWs3jFFZJ2ttTOgTs+T2aheA==, } peerDependencies: - react: 0.0.0-experimental-65b3449c8-20221005 + react: 0.0.0-experimental-e40893d09-20221005 dependencies: loose-envify: 1.4.0 react: 18.2.0 - scheduler: 0.0.0-experimental-65b3449c8-20221005 + scheduler: 0.0.0-experimental-e40893d09-20221005 dev: true /react-dom/17.0.2_react@18.2.0: @@ -25345,10 +25345,10 @@ packages: react-lifecycles-compat: 3.0.4 dev: true - /react/0.0.0-experimental-65b3449c8-20221005: + /react/0.0.0-experimental-e40893d09-20221005: resolution: { - integrity: sha512-JzDw7MRIZPNWiwk/d5tAlB9Ol0LveXNV03Iz8Q5OQ3+zaNTDQYg1s3uCPUKaG2qi3z9JrkV3wjmN2gbc7G9KfQ==, + integrity: sha512-Ecty2+zCaj6yG/4QC5cdhwRQ2kF3FuMMniyUxvmfvtlz9oOMus3tQpnEeITD01rN/nkDO8CXqQfdChSk/qVL6w==, } engines: { node: '>=0.10.0' } dependencies: @@ -26721,10 +26721,10 @@ packages: xmlchars: 2.2.0 dev: true - /scheduler/0.0.0-experimental-65b3449c8-20221005: + /scheduler/0.0.0-experimental-e40893d09-20221005: resolution: { - integrity: sha512-SPjqfOVw94GbPZah2aI74S78QR4LQ8CQ4JPIaVVwbdkQRtVjxEb5pWxFtCN0lyAZdA8T2Hox3fhxpbaIxbohVg==, + integrity: sha512-rvE4D7bJ9P97/Ukc8zh3fTbRi5kGB4xBus3fuWhs1afwSJH7P5LIo6mtL9eO7o69KdxyYfcjjIB2i+P8yrSOGA==, } dependencies: loose-envify: 1.4.0 @@ -30816,7 +30816,10 @@ packages: dev: true /yauzl/2.10.0: - resolution: { integrity: sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= } + resolution: + { + integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==, + } dependencies: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 From 27fe5c8c286a0fb38865e49fce55d97f2bd8d325 Mon Sep 17 00:00:00 2001 From: Meno Abels Date: Thu, 6 Oct 2022 20:56:13 +0200 Subject: [PATCH 03/13] Add response stream errorhandling in edge-function-runtime (#41102) The behaviour of edge-function-runtime in the case of an error was not identical to the edge-runtime. If a type other than "Uint8Array" is written to the Response stream a unhandledreject is raised and logged. The current implementations(nodejs) accepts also Buffers and Strings which causes that a Application Developer things our stream implementation is broken if it is executed as worker. We introduced a helper function to consume the response stream and write the "Uint8Array" stream chunks to the server implementation. Due to the complication that the error side effect is emitted via the unhandledrejection handler it is almost impossible to test --- jest does not allow testing of the unhandlerejections. We tested extendsiveliy the helper in the edge-runtime so that this PR integrates just the consuming function. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper --- packages/next/server/body-streams.ts | 17 ---- packages/next/server/dev/next-dev-server.ts | 20 ++--- packages/next/server/next-server.ts | 16 +++- .../pages/api/test.js | 14 ++++ .../test/index.test.ts | 81 +++++++++++++++++++ 5 files changed, 118 insertions(+), 30 deletions(-) create mode 100644 test/integration/edge-runtime-streaming-error/pages/api/test.js create mode 100644 test/integration/edge-runtime-streaming-error/test/index.test.ts diff --git a/packages/next/server/body-streams.ts b/packages/next/server/body-streams.ts index f5bd6dfe172bc..0951502f5b7a3 100644 --- a/packages/next/server/body-streams.ts +++ b/packages/next/server/body-streams.ts @@ -17,23 +17,6 @@ export function requestToBodyStream( }) } -export function bodyStreamToNodeStream( - bodyStream: ReadableStream -): Readable { - const reader = bodyStream.getReader() - return Readable.from( - (async function* () { - while (true) { - const { done, value } = await reader.read() - if (done) { - return - } - yield value - } - })() - ) -} - function replaceRequestBody( base: T, stream: Readable diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index 8b4da6444666d..c5a88fce6c4e5 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -978,16 +978,18 @@ export default class DevServer extends Server { try { return await super.run(req, res, parsedUrl) } catch (error) { - res.statusCode = 500 const err = getProperError(error) - try { - this.logErrorWithOriginalStack(err).catch(() => {}) - return await this.renderError(err, req, res, pathname!, { - __NEXT_PAGE: (isError(err) && err.page) || pathname || '', - }) - } catch (internalErr) { - console.error(internalErr) - res.body('Internal Server Error').send() + this.logErrorWithOriginalStack(err).catch(() => {}) + if (!res.sent) { + res.statusCode = 500 + try { + return await this.renderError(err, req, res, pathname!, { + __NEXT_PAGE: (isError(err) && err.page) || pathname || '', + }) + } catch (internalErr) { + console.error(internalErr) + res.body('Internal Server Error').send() + } } } } diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 54dced8895134..b68879ff7ffef 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -68,6 +68,7 @@ import { ParsedUrl, parseUrl } from '../shared/lib/router/utils/parse-url' import { parse as nodeParseUrl } from 'url' import * as Log from '../build/output/log' import loadRequireHook from '../build/webpack/require-hook' +import { consumeUint8ArrayReadableStream } from 'next/dist/compiled/edge-runtime' import BaseServer, { Options, @@ -95,7 +96,7 @@ import { getCustomRoute, stringifyQuery } from './server-route-utils' import { urlQueryToSearchParams } from '../shared/lib/router/utils/querystring' import { removeTrailingSlash } from '../shared/lib/router/utils/remove-trailing-slash' import { getNextPathnameInfo } from '../shared/lib/router/utils/get-next-pathname-info' -import { bodyStreamToNodeStream, getClonableBody } from './body-streams' +import { getClonableBody } from './body-streams' import { checkIsManualRevalidate } from './api-utils' import { shouldUseReactRoot, isTargetLikeServerless } from './utils' import ResponseCache from './response-cache' @@ -2122,9 +2123,16 @@ export default class NextNodeServer extends BaseServer { if (result.response.body) { // TODO(gal): not sure that we always need to stream - bodyStreamToNodeStream(result.response.body).pipe( - (params.res as NodeNextResponse).originalResponse - ) + const nodeResStream = (params.res as NodeNextResponse).originalResponse + try { + for await (const chunk of consumeUint8ArrayReadableStream( + result.response.body + )) { + nodeResStream.write(chunk) + } + } finally { + nodeResStream.end() + } } else { ;(params.res as NodeNextResponse).originalResponse.end() } diff --git a/test/integration/edge-runtime-streaming-error/pages/api/test.js b/test/integration/edge-runtime-streaming-error/pages/api/test.js new file mode 100644 index 0000000000000..b5d485fcd223a --- /dev/null +++ b/test/integration/edge-runtime-streaming-error/pages/api/test.js @@ -0,0 +1,14 @@ +export const config = { + runtime: 'experimental-edge', +} +export default function () { + return new Response( + new ReadableStream({ + start(ctr) { + ctr.enqueue(new TextEncoder().encode('hello')) + ctr.enqueue(true) + ctr.close() + }, + }) + ) +} diff --git a/test/integration/edge-runtime-streaming-error/test/index.test.ts b/test/integration/edge-runtime-streaming-error/test/index.test.ts new file mode 100644 index 0000000000000..1f25873dae63b --- /dev/null +++ b/test/integration/edge-runtime-streaming-error/test/index.test.ts @@ -0,0 +1,81 @@ +import stripAnsi from 'next/dist/compiled/strip-ansi' +import { + fetchViaHTTP, + findPort, + killApp, + launchApp, + nextBuild, + nextStart, + waitFor, +} from 'next-test-utils' +import path from 'path' +import { remove } from 'fs-extra' + +const appDir = path.join(__dirname, '..') + +function test(context: ReturnType) { + return async () => { + const res = await fetchViaHTTP(context.appPort, '/api/test') + expect(await res.text()).toEqual('hello') + expect(res.status).toBe(200) + await waitFor(200) + const santizedOutput = stripAnsi(context.output) + expect(santizedOutput).toMatch( + new RegExp(`TypeError: This ReadableStream did not return bytes.`, 'm') + ) + expect(santizedOutput).not.toContain('webpack-internal:') + } +} + +function createContext() { + const ctx = { + output: '', + appPort: -1, + app: undefined, + handler: { + onStdout(msg) { + this.output += msg + }, + onStderr(msg) { + this.output += msg + }, + }, + } + ctx.handler.onStderr = ctx.handler.onStderr.bind(ctx) + ctx.handler.onStdout = ctx.handler.onStdout.bind(ctx) + return ctx +} + +describe('dev mode', () => { + const context = createContext() + + beforeAll(async () => { + context.appPort = await findPort() + context.app = await launchApp(appDir, context.appPort, { + ...context.handler, + env: { __NEXT_TEST_WITH_DEVTOOL: 1 }, + }) + }) + + afterAll(() => killApp(context.app)) + + it('logs the error correctly', test(context)) +}) + +describe('production mode', () => { + const context = createContext() + + beforeAll(async () => { + await remove(path.join(appDir, '.next')) + await nextBuild(appDir, undefined, { + stderr: true, + stdout: true, + }) + context.appPort = await findPort() + context.app = await nextStart(appDir, context.appPort, { + ...context.handler, + }) + }) + afterAll(() => killApp(context.app)) + it('logs the error correctly', test(context)) +}) From dd3e005c93cbf1144ffe99349ac7c988b985b317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Thu, 6 Oct 2022 21:24:42 +0200 Subject: [PATCH 04/13] App font file preload (#41158) Finds the font files connected to font loader modules and adds them to the font loader manifest. They're then collected and rendered similarly to CSS links in app-render. --- packages/next/build/webpack-config.ts | 7 +- .../plugins/font-loader-manifest-plugin.ts | 49 ++++++++++++++ packages/next/server/app-render.tsx | 56 ++++++++++++++++ test/e2e/app-dir/next-font.test.ts | 66 +++++++++++++++++++ test/e2e/app-dir/next-font/app/Comp.js | 2 +- test/e2e/app-dir/next-font/app/client/Comp.js | 2 +- .../app-dir/next-font/app/client/layout.js | 2 +- test/e2e/app-dir/next-font/app/client/page.js | 2 +- test/e2e/app-dir/next-font/app/layout.js | 2 +- test/e2e/app-dir/next-font/app/page.js | 2 +- test/e2e/app-dir/next-font/fonts/font1.js | 5 ++ test/e2e/app-dir/next-font/fonts/font2.js | 5 ++ test/e2e/app-dir/next-font/fonts/font3.js | 9 +++ test/e2e/app-dir/next-font/fonts/font4.js | 5 ++ test/e2e/app-dir/next-font/fonts/font5.js | 9 +++ test/e2e/app-dir/next-font/fonts/font6.js | 5 ++ test/e2e/app-dir/next-font/fonts/fonts.js | 12 ---- 17 files changed, 220 insertions(+), 20 deletions(-) create mode 100644 test/e2e/app-dir/next-font/fonts/font1.js create mode 100644 test/e2e/app-dir/next-font/fonts/font2.js create mode 100644 test/e2e/app-dir/next-font/fonts/font3.js create mode 100644 test/e2e/app-dir/next-font/fonts/font4.js create mode 100644 test/e2e/app-dir/next-font/fonts/font5.js create mode 100644 test/e2e/app-dir/next-font/fonts/font6.js delete mode 100644 test/e2e/app-dir/next-font/fonts/fonts.js diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 0293a1998ba4d..c26ba00d51b20 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1964,8 +1964,11 @@ export default async function getBaseWebpackConfig( !!config.experimental.sri?.algorithm && new SubresourceIntegrityPlugin(config.experimental.sri.algorithm), isClient && - config.experimental.fontLoaders && - new FontLoaderManifestPlugin(), + fontLoaderTargets && + new FontLoaderManifestPlugin({ + appDirEnabled: !!config.experimental.appDir, + fontLoaderTargets, + }), !dev && isClient && new (require('./webpack/plugins/telemetry-plugin').TelemetryPlugin)( diff --git a/packages/next/build/webpack/plugins/font-loader-manifest-plugin.ts b/packages/next/build/webpack/plugins/font-loader-manifest-plugin.ts index c68992af80e14..fee159bd12134 100644 --- a/packages/next/build/webpack/plugins/font-loader-manifest-plugin.ts +++ b/packages/next/build/webpack/plugins/font-loader-manifest-plugin.ts @@ -6,13 +6,41 @@ export type FontLoaderManifest = { pages: { [path: string]: string[] } + app: { + [moduleRequest: string]: string[] + } } const PLUGIN_NAME = 'FontLoaderManifestPlugin' // Creates a manifest of all fonts that should be preloaded given a route export class FontLoaderManifestPlugin { + private appDirEnabled: boolean + private fontLoaderTargets: string[] + + constructor(options: { + appDirEnabled: boolean + fontLoaderTargets: string[] + }) { + this.appDirEnabled = options.appDirEnabled + this.fontLoaderTargets = options.fontLoaderTargets + } + apply(compiler: webpack.Compiler) { compiler.hooks.make.tap(PLUGIN_NAME, (compilation) => { + let fontLoaderModules: webpack.Module[] + + // Get all font loader modules + if (this.appDirEnabled) { + compilation.hooks.finishModules.tap(PLUGIN_NAME, (modules) => { + const modulesArr = Array.from(modules) + fontLoaderModules = modulesArr.filter((mod: any) => + this.fontLoaderTargets.some((fontLoaderTarget) => + mod.userRequest?.startsWith(`${fontLoaderTarget}?`) + ) + ) + }) + } + compilation.hooks.processAssets.tap( { name: PLUGIN_NAME, @@ -21,6 +49,27 @@ export class FontLoaderManifestPlugin { (assets: any) => { const fontLoaderManifest: FontLoaderManifest = { pages: {}, + app: {}, + } + + if (this.appDirEnabled) { + for (const mod of fontLoaderModules) { + const modAssets = Object.keys(mod.buildInfo.assets) + const fontFiles: string[] = modAssets.filter((file: string) => + /\.(woff|woff2|eot|ttf|otf)$/.test(file) + ) + + // Font files ending with .p.(woff|woff2|eot|ttf|otf) are preloaded + const preloadedFontFiles: string[] = fontFiles.filter( + (file: string) => /\.p.(woff|woff2|eot|ttf|otf)$/.test(file) + ) + + // Create an entry for the request even if no files should preload. If that's the case a preconnect tag is added. + if (fontFiles.length > 0) { + fontLoaderManifest.app[(mod as any).userRequest] = + preloadedFontFiles + } + } } for (const entrypoint of compilation.entrypoints.values()) { diff --git a/packages/next/server/app-render.tsx b/packages/next/server/app-render.tsx index 5697cef3dfcda..6799771bb0c33 100644 --- a/packages/next/server/app-render.tsx +++ b/packages/next/server/app-render.tsx @@ -1,6 +1,7 @@ import type { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http' import type { LoadComponentsReturnType } from './load-components' import type { ServerRuntime } from '../types' +import type { FontLoaderManifest } from '../build/webpack/plugins/font-loader-manifest-plugin' // TODO-APP: change to React.use once it becomes stable // @ts-ignore @@ -139,6 +140,7 @@ export type RenderOptsPartial = { runtime?: ServerRuntime serverComponents?: boolean assetPrefix?: string + fontLoaderManifest?: FontLoaderManifest } export type RenderOpts = LoadComponentsReturnType & RenderOptsPartial @@ -532,6 +534,40 @@ function getCssInlinedLinkTags( return [...chunks] } +/** + * Get inline tags based on server CSS manifest and font loader manifest. Only used when rendering to HTML. + */ +function getPreloadedFontFilesInlineLinkTags( + serverComponentManifest: FlightManifest, + serverCSSManifest: FlightCSSManifest, + fontLoaderManifest: FontLoaderManifest | undefined, + filePath?: string +): string[] { + if (!fontLoaderManifest || !filePath) { + return [] + } + const layoutOrPageCss = + serverCSSManifest[filePath] || + serverComponentManifest.__client_css_manifest__?.[filePath] + + if (!layoutOrPageCss) { + return [] + } + + const fontFiles = new Set() + + for (const css of layoutOrPageCss) { + const preloadedFontFiles = fontLoaderManifest.app[css] + if (preloadedFontFiles) { + for (const fontFile of preloadedFontFiles) { + fontFiles.add(fontFile) + } + } + } + + return [...fontFiles] +} + function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined { const directives = cspHeaderValue // Directives are split by ';'. @@ -686,6 +722,7 @@ export async function renderToHTMLOrFlight( supportsDynamicHTML, ComponentMod, dev, + fontLoaderManifest, } = renderOpts patchFetch(ComponentMod) @@ -896,6 +933,12 @@ export async function renderToHTMLOrFlight( layoutOrPagePath ) : [] + const preloadedFontFiles = getPreloadedFontFilesInlineLinkTags( + serverComponentManifest, + serverCSSManifest!, + fontLoaderManifest, + layoutOrPagePath + ) const Template = template ? await interopDefault(template()) : React.Fragment @@ -1074,6 +1117,19 @@ export async function renderToHTMLOrFlight( return ( <> + {preloadedFontFiles.map((fontFile) => { + const ext = /\.(woff|woff2|eot|ttf|otf)$/.exec(fontFile)![1] + return ( + + ) + })} {stylesheets ? stylesheets.map((href) => ( { ).toBe('normal') }) }) + + describe('preload', () => { + it('should preload correctly with server components', async () => { + const html = await renderViaHTTP(next.url, '/') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + expect($('link[as="font"]').length).toBe(3) + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48.p.woff2', + rel: 'preload', + type: 'font/woff2', + }) + expect($('link[as="font"]').get(1).attribs).toEqual({ + as: 'font', + crossorigin: '', + href: '/_next/static/media/b2104791981359ae.p.woff2', + rel: 'preload', + type: 'font/woff2', + }) + expect($('link[as="font"]').get(2).attribs).toEqual({ + as: 'font', + crossorigin: '', + href: '/_next/static/media/b61859a50be14c53.p.woff2', + rel: 'preload', + type: 'font/woff2', + }) + }) + + it('should preload correctly with client components', async () => { + const html = await renderViaHTTP(next.url, '/client') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + expect($('link[as="font"]').length).toBe(3) + // From root layout + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48.p.woff2', + rel: 'preload', + type: 'font/woff2', + }) + + expect($('link[as="font"]').get(1).attribs).toEqual({ + as: 'font', + crossorigin: '', + href: '/_next/static/media/e1053f04babc7571.p.woff2', + rel: 'preload', + type: 'font/woff2', + }) + expect($('link[as="font"]').get(2).attribs).toEqual({ + as: 'font', + crossorigin: '', + href: '/_next/static/media/feab2c68f2a8e9a4.p.woff2', + rel: 'preload', + type: 'font/woff2', + }) + }) + }) }) diff --git a/test/e2e/app-dir/next-font/app/Comp.js b/test/e2e/app-dir/next-font/app/Comp.js index 910cef30bc6ce..37719b67dfbc2 100644 --- a/test/e2e/app-dir/next-font/app/Comp.js +++ b/test/e2e/app-dir/next-font/app/Comp.js @@ -1,4 +1,4 @@ -import { font3 } from '../fonts/fonts' +import font3 from '../fonts/font3' export default function Component() { return ( diff --git a/test/e2e/app-dir/next-font/app/client/Comp.js b/test/e2e/app-dir/next-font/app/client/Comp.js index 39ed805c6de7e..b193e29cfa693 100644 --- a/test/e2e/app-dir/next-font/app/client/Comp.js +++ b/test/e2e/app-dir/next-font/app/client/Comp.js @@ -1,5 +1,5 @@ 'client' -import { font6 } from '../../fonts/fonts' +import font6 from '../../fonts/font6' export default function Component() { return ( diff --git a/test/e2e/app-dir/next-font/app/client/layout.js b/test/e2e/app-dir/next-font/app/client/layout.js index 50678ce7e7ae0..336437d3a1e73 100644 --- a/test/e2e/app-dir/next-font/app/client/layout.js +++ b/test/e2e/app-dir/next-font/app/client/layout.js @@ -1,5 +1,5 @@ 'client' -import { font4 } from '../../fonts/fonts' +import font4 from '../../fonts/font4' export default function Root({ children }) { return ( diff --git a/test/e2e/app-dir/next-font/app/client/page.js b/test/e2e/app-dir/next-font/app/client/page.js index ec6be5bf1ca15..9b6babb684c66 100644 --- a/test/e2e/app-dir/next-font/app/client/page.js +++ b/test/e2e/app-dir/next-font/app/client/page.js @@ -1,6 +1,6 @@ 'client' import Comp from './Comp' -import { font5 } from '../../fonts/fonts' +import font5 from '../../fonts/font5' export default function HomePage() { return ( diff --git a/test/e2e/app-dir/next-font/app/layout.js b/test/e2e/app-dir/next-font/app/layout.js index 9809bfff6f1b4..15d1cf9dff20f 100644 --- a/test/e2e/app-dir/next-font/app/layout.js +++ b/test/e2e/app-dir/next-font/app/layout.js @@ -1,4 +1,4 @@ -import { font1 } from '../fonts/fonts' +import font1 from '../fonts/font1' export default function Root({ children }) { return ( diff --git a/test/e2e/app-dir/next-font/app/page.js b/test/e2e/app-dir/next-font/app/page.js index 74081110014a9..f56f0f85982c0 100644 --- a/test/e2e/app-dir/next-font/app/page.js +++ b/test/e2e/app-dir/next-font/app/page.js @@ -1,5 +1,5 @@ import Comp from './Comp' -import { font2 } from '../fonts/fonts' +import font2 from '../fonts/font2' export default function HomePage() { return ( diff --git a/test/e2e/app-dir/next-font/fonts/font1.js b/test/e2e/app-dir/next-font/fonts/font1.js new file mode 100644 index 0000000000000..7d768d0f49b7b --- /dev/null +++ b/test/e2e/app-dir/next-font/fonts/font1.js @@ -0,0 +1,5 @@ +import localFont from '@next/font/local' + +const font1 = localFont({ src: './font1.woff2', variable: '--font-1' }) + +export default font1 diff --git a/test/e2e/app-dir/next-font/fonts/font2.js b/test/e2e/app-dir/next-font/fonts/font2.js new file mode 100644 index 0000000000000..bfbc65a5a2349 --- /dev/null +++ b/test/e2e/app-dir/next-font/fonts/font2.js @@ -0,0 +1,5 @@ +import localFont from '@next/font/local' + +export const font2 = localFont({ src: './font2.woff2', variable: '--font-2' }) + +export default font2 diff --git a/test/e2e/app-dir/next-font/fonts/font3.js b/test/e2e/app-dir/next-font/fonts/font3.js new file mode 100644 index 0000000000000..7d482753f77b5 --- /dev/null +++ b/test/e2e/app-dir/next-font/fonts/font3.js @@ -0,0 +1,9 @@ +import localFont from '@next/font/local' + +export const font3 = localFont({ + src: './font3.woff2', + weight: '900', + style: 'italic', +}) + +export default font3 diff --git a/test/e2e/app-dir/next-font/fonts/font4.js b/test/e2e/app-dir/next-font/fonts/font4.js new file mode 100644 index 0000000000000..2233f7db242d5 --- /dev/null +++ b/test/e2e/app-dir/next-font/fonts/font4.js @@ -0,0 +1,5 @@ +import localFont from '@next/font/local' + +export const font4 = localFont({ src: './font4.woff2', weight: '100' }) + +export default font4 diff --git a/test/e2e/app-dir/next-font/fonts/font5.js b/test/e2e/app-dir/next-font/fonts/font5.js new file mode 100644 index 0000000000000..828fc27d22725 --- /dev/null +++ b/test/e2e/app-dir/next-font/fonts/font5.js @@ -0,0 +1,9 @@ +import localFont from '@next/font/local' + +export const font5 = localFont({ + src: './font5.woff2', + style: 'italic', + preload: false, +}) + +export default font5 diff --git a/test/e2e/app-dir/next-font/fonts/font6.js b/test/e2e/app-dir/next-font/fonts/font6.js new file mode 100644 index 0000000000000..f2b1e43e4a4b0 --- /dev/null +++ b/test/e2e/app-dir/next-font/fonts/font6.js @@ -0,0 +1,5 @@ +import localFont from '@next/font/local' + +export const font6 = localFont({ src: './font6.woff2' }) + +export default font6 diff --git a/test/e2e/app-dir/next-font/fonts/fonts.js b/test/e2e/app-dir/next-font/fonts/fonts.js deleted file mode 100644 index 5fbe4080b78d0..0000000000000 --- a/test/e2e/app-dir/next-font/fonts/fonts.js +++ /dev/null @@ -1,12 +0,0 @@ -import localFont from '@next/font/local' - -export const font1 = localFont({ src: './font1.woff2', variable: '--font-1' }) -export const font2 = localFont({ src: './font2.woff2', variable: '--font-2' }) -export const font3 = localFont({ - src: './font3.woff2', - weight: '900', - style: 'italic', -}) -export const font4 = localFont({ src: './font4.woff2', weight: '100' }) -export const font5 = localFont({ src: './font5.woff2', style: 'italic' }) -export const font6 = localFont({ src: './font6.woff2' }) From 4e0731fbbe4680933318507eb991645478629b24 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 6 Oct 2022 12:43:23 -0700 Subject: [PATCH 05/13] Fix app static generation cases (#41172) Co-authored-by: Tim Neutkens Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- packages/next/client/components/reducer.ts | 31 ++++--- packages/next/export/worker.ts | 5 +- packages/next/server/app-render.tsx | 93 +++++++++++-------- packages/next/server/base-server.ts | 57 ++++++++---- packages/next/server/next-server.ts | 15 ++- packages/next/server/render-result.ts | 3 +- packages/next/server/send-payload/index.ts | 4 +- packages/next/server/web-server.ts | 3 +- test/e2e/app-dir/app-static.test.ts | 66 ++++++++++++- .../app-static/app/blog/[author]/page.js | 32 +++++++ .../dynamic-no-gen-params-ssr/[slug]/page.js | 12 +++ .../app/dynamic-no-gen-params/[slug]/page.js | 20 ++++ .../(mpa-navigation)/(route-group)/layout.js | 5 + .../(mpa-navigation)/basic-route/layout.js | 5 + .../app/(mpa-navigation)/dynamic/layout.js | 5 + .../(mpa-navigation)/to-pages-dir/layout.js | 5 + .../with-parallel-routes/layout.js | 5 + .../app/(required-tags)/has-tags/layout.js | 5 + .../(required-tags)/missing-tags/layout.js | 5 + 19 files changed, 294 insertions(+), 82 deletions(-) create mode 100644 test/e2e/app-dir/app-static/app/dynamic-no-gen-params-ssr/[slug]/page.js create mode 100644 test/e2e/app-dir/app-static/app/dynamic-no-gen-params/[slug]/page.js diff --git a/packages/next/client/components/reducer.ts b/packages/next/client/components/reducer.ts index ff7517af44a6d..73bd8bea37587 100644 --- a/packages/next/client/components/reducer.ts +++ b/packages/next/client/components/reducer.ts @@ -237,7 +237,6 @@ function fillCacheWithPrefetchedSubTreeData( const existingChildCacheNode = existingChildSegmentMap.get(segmentForCache) - // In case of last segment start the fetch at this level and don't copy further down. if (isLastEntry) { if (!existingChildCacheNode) { existingChildSegmentMap.set(segmentForCache, { @@ -772,8 +771,6 @@ function clientReducer( href ) - // Fill in the cache with blank that holds the `data` field. - // TODO-APP: segments.slice(1) strips '', we can get rid of '' altogether. // Copy subTreeData for the root node of the cache. cache.subTreeData = state.cache.subTreeData @@ -782,6 +779,7 @@ function clientReducer( const res = fillCacheWithDataProperty( cache, state.cache, + // TODO-APP: segments.slice(1) strips '', we can get rid of '' altogether. segments.slice(1), () => fetchServerResponse(url, optimisticTree) ) @@ -839,7 +837,7 @@ function clientReducer( const flightDataPath = flightData[0] // The one before last item is the router state tree patch - const [treePatch] = flightDataPath.slice(-2) + const [treePatch, subTreeData] = flightDataPath.slice(-2) // Path without the last segment, router state, and the subTreeData const flightSegmentPath = flightDataPath.slice(0, -3) @@ -865,10 +863,14 @@ function clientReducer( mutable.previousTree = state.tree mutable.patchedTree = newTree - // Copy subTreeData for the root node of the cache. - cache.subTreeData = state.cache.subTreeData - // Create a copy of the existing cache with the subTreeData applied. - fillCacheWithNewSubTreeData(cache, state.cache, flightDataPath) + if (flightDataPath.length === 2) { + cache.subTreeData = subTreeData + } else { + // Copy subTreeData for the root node of the cache. + cache.subTreeData = state.cache.subTreeData + // Create a copy of the existing cache with the subTreeData applied. + fillCacheWithNewSubTreeData(cache, state.cache, flightDataPath) + } return { // Set href. @@ -939,7 +941,7 @@ function clientReducer( // Slices off the last segment (which is at -3) as it doesn't exist in the tree yet const treePath = flightDataPath.slice(0, -3) - const [treePatch] = flightDataPath.slice(-2) + const [treePatch, subTreeData] = flightDataPath.slice(-2) const newTree = applyRouterStatePatchToTree( // TODO-APP: remove '' @@ -962,9 +964,14 @@ function clientReducer( mutable.patchedTree = newTree - // Copy subTreeData for the root node of the cache. - cache.subTreeData = state.cache.subTreeData - fillCacheWithNewSubTreeData(cache, state.cache, flightDataPath) + // Root refresh + if (flightDataPath.length === 2) { + cache.subTreeData = subTreeData + } else { + // Copy subTreeData for the root node of the cache. + cache.subTreeData = state.cache.subTreeData + fillCacheWithNewSubTreeData(cache, state.cache, flightDataPath) + } return { // Keep href as it was set during navigate / restore diff --git a/packages/next/export/worker.ts b/packages/next/export/worker.ts index eaadc3edb31d3..93c265b698eb0 100644 --- a/packages/next/export/worker.ts +++ b/packages/next/export/worker.ts @@ -96,6 +96,7 @@ interface RenderOpts { defaultLocale?: string domainLocales?: DomainLocale[] trailingSlash?: boolean + supportsDynamicHTML?: boolean } type ComponentModule = ComponentType<{}> & { @@ -389,6 +390,7 @@ export default async function exportPage({ ? requireFontManifest(distDir, serverless) : null, locale: locale as string, + supportsDynamicHTML: false, } // during build we attempt rendering app dir paths @@ -406,8 +408,7 @@ export default async function exportPage({ res as any, page, query, - curRenderOpts as any, - true + curRenderOpts as any ) const html = result?.toUnchunkedString() const flightData = (curRenderOpts as any).pageData diff --git a/packages/next/server/app-render.tsx b/packages/next/server/app-render.tsx index 6799771bb0c33..878805adfb123 100644 --- a/packages/next/server/app-render.tsx +++ b/packages/next/server/app-render.tsx @@ -34,6 +34,7 @@ import { REDIRECT_ERROR_CODE } from '../client/components/redirect' import { NextCookies } from './web/spec-extension/cookies' import { DYNAMIC_ERROR_CODE } from '../client/components/hooks-server-context' import { NOT_FOUND_ERROR_CODE } from '../client/components/not-found' +import { Writable } from 'stream' const INTERNAL_HEADERS_INSTANCE = Symbol('internal for headers readonly') @@ -694,9 +695,22 @@ export async function renderToHTMLOrFlight( res: ServerResponse, pathname: string, query: NextParsedUrlQuery, - renderOpts: RenderOpts, - isStaticGeneration: boolean = false + renderOpts: RenderOpts ): Promise { + /** + * Rules of Static & Dynamic HTML: + * + * 1.) We must generate static HTML unless the caller explicitly opts + * in to dynamic HTML support. + * + * 2.) If dynamic HTML support is requested, we must honor that request + * or throw an error. It is the sole responsibility of the caller to + * ensure they aren't e.g. requesting dynamic HTML for an AMP page. + * + * These rules help ensure that other existing features like request caching, + * coalescing, and ISR continue working as intended. + */ + const isStaticGeneration = renderOpts.supportsDynamicHTML !== true const isFlight = req.headers.__rsc__ !== undefined const capturedErrors: Error[] = [] @@ -719,7 +733,6 @@ export async function renderToHTMLOrFlight( subresourceIntegrityManifest, serverComponentManifest, serverCSSManifest = {}, - supportsDynamicHTML, ComponentMod, dev, fontLoaderManifest, @@ -758,10 +771,10 @@ export async function renderToHTMLOrFlight( /** * Router state provided from the client-side router. Used to handle rendering from the common layout down. */ - const providedFlightRouterState: FlightRouterState = isFlight + let providedFlightRouterState: FlightRouterState = isFlight ? req.headers.__next_router_state_tree__ ? JSON.parse(req.headers.__next_router_state_tree__ as string) - : {} + : undefined : undefined /** @@ -1160,23 +1173,22 @@ export async function renderToHTMLOrFlight( } } - /** - * Rules of Static & Dynamic HTML: - * - * 1.) We must generate static HTML unless the caller explicitly opts - * in to dynamic HTML support. - * - * 2.) If dynamic HTML support is requested, we must honor that request - * or throw an error. It is the sole responsibility of the caller to - * ensure they aren't e.g. requesting dynamic HTML for an AMP page. - * - * These rules help ensure that other existing features like request caching, - * coalescing, and ISR continue working as intended. - */ - const generateStaticHTML = supportsDynamicHTML !== true + const streamToBufferedResult = async ( + renderResult: RenderResult + ): Promise => { + const renderChunks: Buffer[] = [] + const writable = new Writable({ + write(chunk, _encoding, callback) { + renderChunks.push(chunk) + callback() + }, + }) + await renderResult.pipe(writable) + return Buffer.concat(renderChunks).toString() + } // Handle Flight render request. This is only used when client-side navigating. E.g. when you `router.push('/dashboard')` or `router.reload()`. - if (isFlight) { + const generateFlight = async (): Promise => { // TODO-APP: throw on invalid flightRouterState /** * Use router state to decide at what common layout to render the page. @@ -1308,15 +1320,13 @@ export async function renderToHTMLOrFlight( } ).pipeThrough(createBufferedTransformStream()) - if (generateStaticHTML) { - let staticHtml = Buffer.from( - (await readable.getReader().read()).value || '' - ).toString() - return new FlightRenderResult(staticHtml) - } return new FlightRenderResult(readable) } + if (isFlight && !isStaticGeneration) { + return generateFlight() + } + // Below this line is handling for rendering to HTML. // Create full component tree from root to leaf. @@ -1450,7 +1460,7 @@ export async function renderToHTMLOrFlight( return await continueFromInitialStream(renderStream, { dataStream: serverComponentsInlinedTransformStream?.readable, - generateStaticHTML: generateStaticHTML, + generateStaticHTML: isStaticGeneration, getServerInsertedHTML, serverInsertedHTMLToHead: true, polyfills, @@ -1482,7 +1492,7 @@ export async function renderToHTMLOrFlight( return await continueFromInitialStream(renderStream, { dataStream: serverComponentsInlinedTransformStream?.readable, - generateStaticHTML: generateStaticHTML, + generateStaticHTML: isStaticGeneration, getServerInsertedHTML, serverInsertedHTMLToHead: true, polyfills, @@ -1490,31 +1500,34 @@ export async function renderToHTMLOrFlight( }) } } + const renderResult = new RenderResult(await bodyResult()) - if (generateStaticHTML) { - const readable = await bodyResult() - let staticHtml = Buffer.from( - (await readable.getReader().read()).value || '' - ).toString() - + if (isStaticGeneration) { + const htmlResult = await streamToBufferedResult(renderResult) // if we encountered any unexpected errors during build // we fail the prerendering phase and the build if (capturedErrors.length > 0) { throw capturedErrors[0] } + // const before = Buffer.concat( + // serverComponentsRenderOpts.rscChunks + // ).toString() + + // TODO-APP: derive this from same pass to prevent additional + // render during static generation + const filteredFlightData = await streamToBufferedResult( + await generateFlight() + ) - ;(renderOpts as any).pageData = Buffer.concat( - serverComponentsRenderOpts.rscChunks - ).toString() + ;(renderOpts as any).pageData = filteredFlightData ;(renderOpts as any).revalidate = typeof staticGenerationStore?.revalidate === 'undefined' ? defaultRevalidate : staticGenerationStore?.revalidate - return new RenderResult(staticHtml) + return new RenderResult(htmlResult) } - - return new RenderResult(await bodyResult()) + return renderResult } const initialStaticGenerationStore = { diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index 2735dd3382dac..10148095a3499 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -158,7 +158,7 @@ export class WrappedBuildError extends Error { } type ResponsePayload = { - type: 'html' | 'json' + type: 'html' | 'json' | 'rsc' body: RenderResult revalidateOptions?: any } @@ -238,7 +238,7 @@ export default abstract class Server { protected abstract getPublicDir(): string protected abstract getHasStaticDir(): boolean - protected abstract getHasAppDir(): boolean + protected abstract getHasAppDir(dev: boolean): boolean protected abstract getPagesManifest(): PagesManifest | undefined protected abstract getAppPathsManifest(): PagesManifest | undefined protected abstract getBuildId(): string @@ -287,7 +287,7 @@ export default abstract class Server { res: BaseNextResponse, options: { result: RenderResult - type: 'html' | 'json' + type: 'html' | 'json' | 'rsc' generateEtags: boolean poweredByHeader: boolean options?: PayloadOptions @@ -355,7 +355,6 @@ export default abstract class Server { : require('path').join(this.dir, this.nextConfig.distDir) this.publicDir = this.getPublicDir() this.hasStaticDir = !minimalMode && this.getHasStaticDir() - this.hasAppDir = this.getHasAppDir() // Only serverRuntimeConfig needs the default // publicRuntimeConfig gets it's default in client/index.js @@ -369,6 +368,7 @@ export default abstract class Server { this.buildId = this.getBuildId() this.minimalMode = minimalMode || !!process.env.NEXT_PRIVATE_MINIMAL_MODE + this.hasAppDir = this.getHasAppDir(dev) const serverComponents = this.hasAppDir this.serverComponentManifest = serverComponents ? this.getServerComponentManifest() @@ -1001,17 +1001,6 @@ export default abstract class Server { const hasGetInitialProps = !!components.Component?.getInitialProps let isSSG = !!components.getStaticProps - // Toggle whether or not this is a Data request - const isDataReq = - !!( - query.__nextDataReq || - (req.headers['x-nextjs-data'] && - (this.serverOptions as any).webServerConfig) - ) && - (isSSG || hasServerProps) - - delete query.__nextDataReq - // Compute the iSSG cache key. We use the rewroteUrl since // pages with fallback: false are allowed to be rewritten to // and we need to look up the path by the rewritten path @@ -1040,8 +1029,36 @@ export default abstract class Server { if (hasFallback || staticPaths?.includes(resolvedUrlPathname)) { isSSG = true + } else if (!this.renderOpts.dev) { + const manifest = this.getPrerenderManifest() + isSSG = + isSSG || !!manifest.routes[pathname === '/index' ? '/' : pathname] + } + } + + // Toggle whether or not this is a Data request + let isDataReq = + !!( + query.__nextDataReq || + (req.headers['x-nextjs-data'] && + (this.serverOptions as any).webServerConfig) + ) && + (isSSG || hasServerProps) + + if (isAppPath && req.headers['__rsc__']) { + if (isSSG) { + isDataReq = true + // strip header so we generate HTML still + if ( + opts.runtime !== 'experimental-edge' || + (this.serverOptions as any).webServerConfig + ) { + delete req.headers['__rsc__'] + delete req.headers['__next_router_state_tree__'] + } } } + delete query.__nextDataReq // normalize req.url for SSG paths as it is not exposed // to getStaticProps and the asPath should not expose /_next/data @@ -1206,7 +1223,7 @@ export default abstract class Server { } let ssgCacheKey = - isPreviewMode || !isSSG || opts.supportsDynamicHTML || isFlightRequest + isPreviewMode || !isSSG || opts.supportsDynamicHTML ? null // Preview mode, manual revalidate, flight request can bypass the cache : `${locale ? `/${locale}` : ''}${ (pathname === '/' || resolvedUrlPathname === '/') && locale @@ -1564,9 +1581,13 @@ export default abstract class Server { throw new Error('invariant SSG should not return an image cache value') } else { return { - type: isDataReq ? 'json' : 'html', + type: isDataReq ? (isAppPath ? 'rsc' : 'json') : 'html', body: isDataReq - ? RenderResult.fromStatic(JSON.stringify(cachedData.pageData)) + ? RenderResult.fromStatic( + isAppPath + ? (cachedData.pageData as string) + : JSON.stringify(cachedData.pageData) + ) : cachedData.html, revalidateOptions, } diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index b68879ff7ffef..0651cca8bf178 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -475,11 +475,16 @@ export default class NextNodeServer extends BaseServer { ] } - protected getHasAppDir(): boolean { - const appDirectory = join(this.dir, 'app') - return ( - fs.existsSync(appDirectory) && fs.statSync(appDirectory).isDirectory() - ) + protected getHasAppDir(dev: boolean): boolean { + const appDirectory = dev + ? join(this.dir, 'app') + : join(this.serverDistDir, 'app') + + try { + return fs.statSync(appDirectory).isDirectory() + } catch (err) { + return false + } } protected generateStaticRoutes(): Route[] { diff --git a/packages/next/server/render-result.ts b/packages/next/server/render-result.ts index 20b22c3eff228..df0c693738fc6 100644 --- a/packages/next/server/render-result.ts +++ b/packages/next/server/render-result.ts @@ -1,4 +1,5 @@ import type { ServerResponse } from 'http' +import { Writable } from 'stream' type ContentTypeOption = string | undefined @@ -27,7 +28,7 @@ export default class RenderResult { return this._result } - pipe(res: ServerResponse): Promise { + pipe(res: ServerResponse | Writable): Promise { if (typeof this._result === 'string') { throw new Error( 'invariant: static responses cannot be piped. This is a bug in Next.js' diff --git a/packages/next/server/send-payload/index.ts b/packages/next/server/send-payload/index.ts index fc2be15b23445..7a761f17c1853 100644 --- a/packages/next/server/send-payload/index.ts +++ b/packages/next/server/send-payload/index.ts @@ -49,7 +49,7 @@ export async function sendRenderResult({ req: IncomingMessage res: ServerResponse result: RenderResult - type: 'html' | 'json' + type: 'html' | 'json' | 'rsc' generateEtags: boolean poweredByHeader: boolean options?: PayloadOptions @@ -78,6 +78,8 @@ export async function sendRenderResult({ 'Content-Type', resultContentType ? resultContentType + : type === 'rsc' + ? 'application/octet-stream' : type === 'json' ? 'application/json' : 'text/html; charset=utf-8' diff --git a/packages/next/server/web-server.ts b/packages/next/server/web-server.ts index 664accbbaabb4..5cfdaca5c6331 100644 --- a/packages/next/server/web-server.ts +++ b/packages/next/server/web-server.ts @@ -378,8 +378,7 @@ export default class NextWebServer extends BaseServer { Object.assign(renderOpts, { disableOptimizedLoading: true, runtime: 'experimental-edge', - }), - !!pagesRenderToHTML + }) ) } else { throw new Error(`Invariant: curRenderToHTML is missing`) diff --git a/test/e2e/app-dir/app-static.test.ts b/test/e2e/app-dir/app-static.test.ts index 953695f79d3d7..31e493caac63c 100644 --- a/test/e2e/app-dir/app-static.test.ts +++ b/test/e2e/app-dir/app-static.test.ts @@ -4,7 +4,8 @@ import { promisify } from 'util' import path, { join } from 'path' import { createNext, FileRef } from 'e2e-utils' import { NextInstance } from 'test/lib/next-modes/base' -import { fetchViaHTTP, normalizeRegEx } from 'next-test-utils' +import { check, fetchViaHTTP, normalizeRegEx } from 'next-test-utils' +import webdriver from 'next-webdriver' const glob = promisify(globOrig) @@ -56,6 +57,8 @@ describe('app-dir static/dynamic handling', () => { 'blog/tim.rsc', 'blog/tim/first-post.html', 'blog/tim/first-post.rsc', + 'dynamic-no-gen-params-ssr/[slug]/page.js', + 'dynamic-no-gen-params/[slug]/page.js', 'ssr-auto/page.js', 'ssr-forced/page.js', ]) @@ -162,6 +165,32 @@ describe('app-dir static/dynamic handling', () => { } }) + it('should work with forced dynamic path', async () => { + for (const slug of ['first', 'second']) { + const res = await fetchViaHTTP( + next.url, + `/dynamic-no-gen-params-ssr/${slug}`, + undefined, + { redirect: 'manual' } + ) + expect(res.status).toBe(200) + expect(await res.text()).toContain(`${slug}`) + } + }) + + it('should work with dynamic path no generateStaticParams', async () => { + for (const slug of ['first', 'second']) { + const res = await fetchViaHTTP( + next.url, + `/dynamic-no-gen-params/${slug}`, + undefined, + { redirect: 'manual' } + ) + expect(res.status).toBe(200) + expect(await res.text()).toContain(`${slug}`) + } + }) + it('should handle dynamicParams: true correctly', async () => { const paramsToCheck = [ { @@ -200,6 +229,41 @@ describe('app-dir static/dynamic handling', () => { } }) + it('should navigate to static path correctly', async () => { + const browser = await webdriver(next.url, '/blog/tim') + await browser.eval('window.beforeNav = 1') + + expect(await browser.eval('document.documentElement.innerHTML')).toContain( + '/blog/[author]' + ) + await browser.elementByCss('#author-2').click() + + await check(async () => { + const params = JSON.parse(await browser.elementByCss('#params').text()) + return params.author === 'seb' ? 'found' : params + }, 'found') + + expect(await browser.eval('window.beforeNav')).toBe(1) + await browser.elementByCss('#author-1-post-1').click() + + await check(async () => { + const params = JSON.parse(await browser.elementByCss('#params').text()) + return params.author === 'tim' && params.slug === 'first-post' + ? 'found' + : params + }, 'found') + + expect(await browser.eval('window.beforeNav')).toBe(1) + await browser.back() + + await check(async () => { + const params = JSON.parse(await browser.elementByCss('#params').text()) + return params.author === 'seb' ? 'found' : params + }, 'found') + + expect(await browser.eval('window.beforeNav')).toBe(1) + }) + it('should ssr dynamically when detected automatically', async () => { const initialRes = await fetchViaHTTP(next.url, '/ssr-auto', undefined, { redirect: 'manual', diff --git a/test/e2e/app-dir/app-static/app/blog/[author]/page.js b/test/e2e/app-dir/app-static/app/blog/[author]/page.js index 1275c9f59d901..c8e2e05c45033 100644 --- a/test/e2e/app-dir/app-static/app/blog/[author]/page.js +++ b/test/e2e/app-dir/app-static/app/blog/[author]/page.js @@ -1,3 +1,5 @@ +import Link from 'next/link' + export const config = { dynamicParams: false, } @@ -8,6 +10,36 @@ export default function Page({ params }) {

/blog/[author]

{JSON.stringify(params)}

{Date.now()}

+ + /blog/tim + +
+ + /blog/seb + +
+ + /blog/styfle + +
+ + + /blog/tim/first-post + +
+ + /blog/seb/second-post + +
+ + /blog/styfle/first-post + +
+ + + /dynamic-no-gen-params/first + +
) } diff --git a/test/e2e/app-dir/app-static/app/dynamic-no-gen-params-ssr/[slug]/page.js b/test/e2e/app-dir/app-static/app/dynamic-no-gen-params-ssr/[slug]/page.js new file mode 100644 index 0000000000000..972c1ec17d586 --- /dev/null +++ b/test/e2e/app-dir/app-static/app/dynamic-no-gen-params-ssr/[slug]/page.js @@ -0,0 +1,12 @@ +export const config = { + revalidate: 0, +} + +export default function Page({ params }) { + return ( + <> +

/dynamic-no-gen-params-ssr

+

{JSON.stringify(params)}

+ + ) +} diff --git a/test/e2e/app-dir/app-static/app/dynamic-no-gen-params/[slug]/page.js b/test/e2e/app-dir/app-static/app/dynamic-no-gen-params/[slug]/page.js new file mode 100644 index 0000000000000..27b661a09fdca --- /dev/null +++ b/test/e2e/app-dir/app-static/app/dynamic-no-gen-params/[slug]/page.js @@ -0,0 +1,20 @@ +import Link from 'next/link' + +export default function Page({ params }) { + return ( + <> +

/dynamic-no-gen-params

+

{JSON.stringify(params)}

+ + + /dynamic-no-gen-params/second + +
+ + + /blog/styfle + +
+ + ) +} diff --git a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/(route-group)/layout.js b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/(route-group)/layout.js index 05b841b280b3f..cfbc1de9ce956 100644 --- a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/(route-group)/layout.js +++ b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/(route-group)/layout.js @@ -1,3 +1,8 @@ +// TODO-APP: remove after fixing filtering static flight data +export const config = { + revalidate: 0, +} + export default function Root({ children }) { return ( diff --git a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/basic-route/layout.js b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/basic-route/layout.js index 05b841b280b3f..cfbc1de9ce956 100644 --- a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/basic-route/layout.js +++ b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/basic-route/layout.js @@ -1,3 +1,8 @@ +// TODO-APP: remove after fixing filtering static flight data +export const config = { + revalidate: 0, +} + export default function Root({ children }) { return ( diff --git a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/dynamic/layout.js b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/dynamic/layout.js index 05b841b280b3f..cfbc1de9ce956 100644 --- a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/dynamic/layout.js +++ b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/dynamic/layout.js @@ -1,3 +1,8 @@ +// TODO-APP: remove after fixing filtering static flight data +export const config = { + revalidate: 0, +} + export default function Root({ children }) { return ( diff --git a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/to-pages-dir/layout.js b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/to-pages-dir/layout.js index 05b841b280b3f..cfbc1de9ce956 100644 --- a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/to-pages-dir/layout.js +++ b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/to-pages-dir/layout.js @@ -1,3 +1,8 @@ +// TODO-APP: remove after fixing filtering static flight data +export const config = { + revalidate: 0, +} + export default function Root({ children }) { return ( diff --git a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/layout.js b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/layout.js index 267f8d02f2659..bd7c2817d37a5 100644 --- a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/layout.js +++ b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/layout.js @@ -1,3 +1,8 @@ +// TODO-APP: remove after fixing filtering static flight data +export const config = { + revalidate: 0, +} + export default function Root({ one, two }) { return ( diff --git a/test/e2e/app-dir/root-layout/app/(required-tags)/has-tags/layout.js b/test/e2e/app-dir/root-layout/app/(required-tags)/has-tags/layout.js index c84b681925ebc..8d949068ce5b6 100644 --- a/test/e2e/app-dir/root-layout/app/(required-tags)/has-tags/layout.js +++ b/test/e2e/app-dir/root-layout/app/(required-tags)/has-tags/layout.js @@ -1,3 +1,8 @@ +// TODO-APP: remove after fixing filtering static flight data +export const config = { + revalidate: 0, +} + export default function Root({ children }) { return ( diff --git a/test/e2e/app-dir/root-layout/app/(required-tags)/missing-tags/layout.js b/test/e2e/app-dir/root-layout/app/(required-tags)/missing-tags/layout.js index 1b6c561ff3244..82917da557b6c 100644 --- a/test/e2e/app-dir/root-layout/app/(required-tags)/missing-tags/layout.js +++ b/test/e2e/app-dir/root-layout/app/(required-tags)/missing-tags/layout.js @@ -1,3 +1,8 @@ +// TODO-APP: remove after fixing filtering static flight data +export const config = { + revalidate: 0, +} + export default function Root({ children }) { return children } From 5e25bd21410da021ed8a897caf9f0c80fb9ba4a7 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 6 Oct 2022 21:44:28 +0200 Subject: [PATCH 06/13] v12.3.2-canary.22 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/eslint-config-next/package.json | 4 ++-- packages/eslint-plugin-next/package.json | 2 +- packages/font/package.json | 2 +- packages/next-bundle-analyzer/package.json | 2 +- packages/next-codemod/package.json | 2 +- packages/next-env/package.json | 2 +- packages/next-mdx/package.json | 2 +- packages/next-plugin-storybook/package.json | 2 +- packages/next-polyfill-module/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next-swc/package.json | 2 +- packages/next/package.json | 14 +++++++------- packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- pnpm-lock.yaml | 14 +++++++------- 17 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lerna.json b/lerna.json index 7839444900eab..9c5362805f3a6 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "12.3.2-canary.21" + "version": "12.3.2-canary.22" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 5a462468f7994..69efa2564eb0e 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index 113add29a3204..c7e866a9d37cd 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "description": "ESLint configuration used by NextJS.", "main": "index.js", "license": "MIT", @@ -9,7 +9,7 @@ "directory": "packages/eslint-config-next" }, "dependencies": { - "@next/eslint-plugin-next": "12.3.2-canary.21", + "@next/eslint-plugin-next": "12.3.2-canary.22", "@rushstack/eslint-patch": "^1.1.3", "@typescript-eslint/parser": "^5.21.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index c52d68dc96ab5..546a353ae9329 100644 --- a/packages/eslint-plugin-next/package.json +++ b/packages/eslint-plugin-next/package.json @@ -1,6 +1,6 @@ { "name": "@next/eslint-plugin-next", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "description": "ESLint plugin for NextJS.", "main": "dist/index.js", "license": "MIT", diff --git a/packages/font/package.json b/packages/font/package.json index fee85ce4cc864..f777f01168e63 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,6 +1,6 @@ { "name": "@next/font", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index d410c8ae4d667..7c51b864d8880 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 66917ec6f478d..f33b4a30452d8 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "license": "MIT", "dependencies": { "chalk": "4.1.0", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 388e72b8f56f3..d13e426690d6a 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index af3062b9184c8..ae86d7c43f699 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index 286a33078832b..cf5df88799dac 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-storybook" diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json index 44752dd815c29..5ee66f4a296c1 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)", "main": "dist/polyfill-module.js", "license": "MIT", diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index df6b887443859..6b8000474b566 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index 6d5afb298cb7b..d432cae42643f 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "private": true, "scripts": { "build-native": "napi build --platform -p next-swc-napi --cargo-name next_swc_napi native --features plugin", diff --git a/packages/next/package.json b/packages/next/package.json index 20ccaeffed422..e44a9173126c3 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -69,7 +69,7 @@ ] }, "dependencies": { - "@next/env": "12.3.2-canary.21", + "@next/env": "12.3.2-canary.22", "@swc/helpers": "0.4.11", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", @@ -120,11 +120,11 @@ "@hapi/accept": "5.0.2", "@napi-rs/cli": "2.7.0", "@napi-rs/triples": "1.1.0", - "@next/polyfill-module": "12.3.2-canary.21", - "@next/polyfill-nomodule": "12.3.2-canary.21", - "@next/react-dev-overlay": "12.3.2-canary.21", - "@next/react-refresh-utils": "12.3.2-canary.21", - "@next/swc": "12.3.2-canary.21", + "@next/polyfill-module": "12.3.2-canary.22", + "@next/polyfill-nomodule": "12.3.2-canary.22", + "@next/react-dev-overlay": "12.3.2-canary.22", + "@next/react-refresh-utils": "12.3.2-canary.22", + "@next/swc": "12.3.2-canary.22", "@segment/ajv-human-errors": "2.1.2", "@taskr/clear": "1.1.0", "@taskr/esnext": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index c3a8023aeea99..f066f0aaf1edb 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-dev-overlay", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "description": "A development-only overlay for developing React applications.", "repository": { "url": "vercel/next.js", diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index 237894170429d..2a7b8d77633ff 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-refresh-utils", - "version": "12.3.2-canary.21", + "version": "12.3.2-canary.22", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index caf19ef7c2d7b..183412b1d9ef6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -397,7 +397,7 @@ importers: packages/eslint-config-next: specifiers: - '@next/eslint-plugin-next': 12.3.2-canary.21 + '@next/eslint-plugin-next': 12.3.2-canary.22 '@rushstack/eslint-patch': ^1.1.3 '@typescript-eslint/parser': ^5.21.0 eslint-import-resolver-node: ^0.3.6 @@ -458,12 +458,12 @@ importers: '@hapi/accept': 5.0.2 '@napi-rs/cli': 2.7.0 '@napi-rs/triples': 1.1.0 - '@next/env': 12.3.2-canary.21 - '@next/polyfill-module': 12.3.2-canary.21 - '@next/polyfill-nomodule': 12.3.2-canary.21 - '@next/react-dev-overlay': 12.3.2-canary.21 - '@next/react-refresh-utils': 12.3.2-canary.21 - '@next/swc': 12.3.2-canary.21 + '@next/env': 12.3.2-canary.22 + '@next/polyfill-module': 12.3.2-canary.22 + '@next/polyfill-nomodule': 12.3.2-canary.22 + '@next/react-dev-overlay': 12.3.2-canary.22 + '@next/react-refresh-utils': 12.3.2-canary.22 + '@next/swc': 12.3.2-canary.22 '@segment/ajv-human-errors': 2.1.2 '@swc/helpers': 0.4.11 '@taskr/clear': 1.1.0 From 87026c893bf0355caa4210b0bb6a60f794b20f66 Mon Sep 17 00:00:00 2001 From: Alex <12097569+nialexsan@users.noreply.github.com> Date: Thu, 6 Oct 2022 12:51:05 -0700 Subject: [PATCH 07/13] Update introduction.md (#41226) Fixed link to phases lines in the documentation ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com> --- docs/api-reference/next.config.js/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-reference/next.config.js/introduction.md b/docs/api-reference/next.config.js/introduction.md index e708004bd1a2e..732b4a32320fe 100644 --- a/docs/api-reference/next.config.js/introduction.md +++ b/docs/api-reference/next.config.js/introduction.md @@ -62,7 +62,7 @@ module.exports = async (phase, { defaultConfig }) => { } ``` -`phase` is the current context in which the configuration is loaded. You can see the [available phases](https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/constants.ts#L1-L5). Phases can be imported from `next/constants`: +`phase` is the current context in which the configuration is loaded. You can see the [available phases](https://github.com/vercel/next.js/blob/5e6b008b561caf2710ab7be63320a3d549474a5b/packages/next/shared/lib/constants.ts#L19-L23). Phases can be imported from `next/constants`: ```js const { PHASE_DEVELOPMENT_SERVER } = require('next/constants') From f83cc0cbed4f1bf72360741241a7dfb0aac88aad Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 7 Oct 2022 00:16:42 +0200 Subject: [PATCH 08/13] Enabel appDir when flag and dir existed at the same time (#41233) If there's an existing folder named `app/` but `appDir` flag is not enabled, do not enabled server components --- packages/next-plugin-storybook/preset.js | 2 +- packages/next/build/index.ts | 8 ++++---- packages/next/build/jest/jest.ts | 4 ++-- packages/next/build/webpack-config.ts | 4 ++-- packages/next/server/base-server.ts | 3 ++- packages/next/server/dev/next-dev-server.ts | 5 ++++- test/e2e/streaming-ssr/index.test.ts | 5 +++++ 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/next-plugin-storybook/preset.js b/packages/next-plugin-storybook/preset.js index 0e83637c8fd4b..d88f476b2152e 100644 --- a/packages/next-plugin-storybook/preset.js +++ b/packages/next-plugin-storybook/preset.js @@ -7,7 +7,7 @@ const CWD = process.cwd() async function webpackFinal(config) { const nextConfig = await loadConfig(PHASE_PRODUCTION_BUILD, CWD) - const pagesDir = findPagesDir(CWD, !!nextConfig.experimental.appDir) + const { pagesDir } = findPagesDir(CWD, !!nextConfig.experimental.appDir) const nextWebpackConfig = await getWebpackConfig(CWD, { pagesDir, entrypoints: {}, diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index c3b13bde241e7..fa66f489f6cff 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -301,8 +301,8 @@ export default async function build( setGlobal('telemetry', telemetry) const publicDir = path.join(dir, 'public') - const hasAppDir = !!config.experimental.appDir - const { pagesDir, appDir } = findPagesDir(dir, hasAppDir) + const isAppDirEnabled = !!config.experimental.appDir + const { pagesDir, appDir } = findPagesDir(dir, isAppDirEnabled) const hasPublicDir = await fileExists(publicDir) @@ -394,7 +394,7 @@ export default async function build( config.experimental.cpus, config.experimental.workerThreads, telemetry, - hasAppDir + isAppDirEnabled && !!appDir ) }), ]) @@ -1988,7 +1988,7 @@ export default async function build( combinedPages.length > 0 || useStatic404 || useDefaultStatic500 || - hasAppDir + isAppDirEnabled ) { const staticGenerationSpan = nextBuildSpan.traceChild('static-generation') diff --git a/packages/next/build/jest/jest.ts b/packages/next/build/jest/jest.ts index cb4b50887e3a7..be176de4f091f 100644 --- a/packages/next/build/jest/jest.ts +++ b/packages/next/build/jest/jest.ts @@ -72,8 +72,8 @@ export default function nextJest(options: { dir?: string } = {}) { isEsmProject = packageConfig.type === 'module' nextConfig = await getConfig(resolvedDir) - const hasAppDir = !!nextConfig.experimental.appDir - const findPagesDirResult = findPagesDir(resolvedDir, hasAppDir) + const isAppDirEnabled = !!nextConfig.experimental.appDir + const findPagesDirResult = findPagesDir(resolvedDir, isAppDirEnabled) hasServerComponents = !!findPagesDirResult.appDir pagesDir = findPagesDirResult.pagesDir setUpEnv(resolvedDir, nextConfig) diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index c26ba00d51b20..7988eb1374948 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -563,7 +563,7 @@ export default async function getBaseWebpackConfig( rewrites.afterFiles.length > 0 || rewrites.fallback.length > 0 - const hasAppDir = !!config.experimental.appDir + const hasAppDir = !!config.experimental.appDir && !!appDir const hasConcurrentFeatures = hasReactRoot const hasServerComponents = hasAppDir @@ -1587,7 +1587,7 @@ export default async function getBaseWebpackConfig( ] : []), // Alias `next/dynamic` to React.lazy implementation for RSC - ...(hasServerComponents && appDir + ...(hasServerComponents ? [ { test: codeCondition.test, diff --git a/packages/next/server/base-server.ts b/packages/next/server/base-server.ts index 10148095a3499..8c03b09b1c298 100644 --- a/packages/next/server/base-server.ts +++ b/packages/next/server/base-server.ts @@ -368,7 +368,8 @@ export default abstract class Server { this.buildId = this.getBuildId() this.minimalMode = minimalMode || !!process.env.NEXT_PRIVATE_MINIMAL_MODE - this.hasAppDir = this.getHasAppDir(dev) + this.hasAppDir = + !!this.nextConfig.experimental.appDir && this.getHasAppDir(dev) const serverComponents = this.hasAppDir this.serverComponentManifest = serverComponents ? this.getServerComponentManifest() diff --git a/packages/next/server/dev/next-dev-server.ts b/packages/next/server/dev/next-dev-server.ts index c5a88fce6c4e5..cc34cfb70d123 100644 --- a/packages/next/server/dev/next-dev-server.ts +++ b/packages/next/server/dev/next-dev-server.ts @@ -191,7 +191,10 @@ export default class DevServer extends Server { this.isCustomServer = !options.isNextDevCommand - const { pagesDir, appDir } = findPagesDir(this.dir, this.hasAppDir) + const { pagesDir, appDir } = findPagesDir( + this.dir, + !!this.nextConfig.experimental.appDir + ) this.pagesDir = pagesDir this.appDir = appDir } diff --git a/test/e2e/streaming-ssr/index.test.ts b/test/e2e/streaming-ssr/index.test.ts index 482346e66ae36..58466bdd5ba07 100644 --- a/test/e2e/streaming-ssr/index.test.ts +++ b/test/e2e/streaming-ssr/index.test.ts @@ -22,6 +22,11 @@ describe('react 18 streaming SSR with custom next configs', () => { beforeAll(async () => { next = await createNext({ files: { + 'app/page.js': ` + export default function Page() { + return 'fake-app' /* this should not enable appDir */ + } + `, pages: new FileRef(join(__dirname, 'streaming-ssr/pages')), }, nextConfig: require(join(__dirname, 'streaming-ssr/next.config.js')), From b5590022b6d6ea1e058380f598c91165b20735ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Fri, 7 Oct 2022 11:15:57 +0200 Subject: [PATCH 09/13] Font loaders next config shape (#41219) Changes how font loaders are configured in next config, makes more sense since options can be optional. Also adds error for when font loaders are used from within node_modules. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `pnpm lint` - [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) --- packages/font/google/index.js | 2 +- packages/font/local/index.js | 2 +- packages/next/build/swc/options.js | 4 ++- packages/next/build/webpack-config.ts | 4 +-- .../build/webpack/config/blocks/css/index.ts | 27 ++++++++++++++----- .../webpack/config/blocks/css/messages.ts | 12 ++++++--- packages/next/server/config-schema.ts | 15 +++++++++-- packages/next/server/config-shared.ts | 2 +- test/e2e/app-dir/next-font/next.config.js | 8 +++--- test/e2e/next-font/app/next.config.js | 13 +++++---- test/e2e/next-font/babel/next.config.js | 9 ++++--- test/e2e/next-font/basepath/next.config.js | 9 ++++--- .../font-loader-in-document/next.config.js | 9 ++++--- .../next.config.js | 13 +++++---- .../without-preloaded-fonts/next.config.js | 9 ++++--- 15 files changed, 92 insertions(+), 46 deletions(-) diff --git a/packages/font/google/index.js b/packages/font/google/index.js index 207253086b485..f3d7e7c80ab0a 100644 --- a/packages/font/google/index.js +++ b/packages/font/google/index.js @@ -1 +1 @@ -throw new Error('@next/font/google is not correctly setup') +throw new Error('@next/font/google is not correctly configured') diff --git a/packages/font/local/index.js b/packages/font/local/index.js index 8b9773a4a1b66..bc2f598aaa23d 100644 --- a/packages/font/local/index.js +++ b/packages/font/local/index.js @@ -1 +1 @@ -throw new Error('@next/font/local is not correctly setup') +throw new Error('@next/font/local is not correctly configured') diff --git a/packages/next/build/swc/options.js b/packages/next/build/swc/options.js index a6d79c13e8c50..6dfb154cd0e1f 100644 --- a/packages/next/build/swc/options.js +++ b/packages/next/build/swc/options.js @@ -134,7 +134,9 @@ function getBaseSWCOptions({ fontLoaders: nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot ? { - fontLoaders: Object.keys(nextConfig.experimental.fontLoaders), + fontLoaders: nextConfig.experimental.fontLoaders.map( + ({ loader }) => loader + ), relativeFilePathFromRoot, } : null, diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 7988eb1374948..20c4adfaf93ea 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1202,8 +1202,8 @@ export default async function getBaseWebpackConfig( const fontLoaderTargets = config.experimental.fontLoaders && - Object.keys(config.experimental.fontLoaders).map((fontLoader) => { - const resolved = require.resolve(fontLoader) + config.experimental.fontLoaders.map(({ loader }) => { + const resolved = require.resolve(loader) return path.join(resolved, '../target.css') }) diff --git a/packages/next/build/webpack/config/blocks/css/index.ts b/packages/next/build/webpack/config/blocks/css/index.ts index bb8a8d8570c2e..8b83a8d300e8a 100644 --- a/packages/next/build/webpack/config/blocks/css/index.ts +++ b/packages/next/build/webpack/config/blocks/css/index.ts @@ -11,6 +11,7 @@ import { getGlobalModuleImportError, getLocalModuleImportError, getFontLoaderDocumentImportError, + getFontLoaderImportError, } from './messages' import { getPostCssPlugins } from './plugins' @@ -183,12 +184,10 @@ export const css = curry(async function css( // Resolve the configured font loaders, the resolved files are noop files that next-font-loader will match let fontLoaders: [string, string][] | undefined = ctx.experimental.fontLoaders - ? Object.entries(ctx.experimental.fontLoaders).map( - ([fontLoader, fontLoaderOptions]: any) => [ - path.join(require.resolve(fontLoader), '../target.css'), - fontLoaderOptions, - ] - ) + ? ctx.experimental.fontLoaders.map(({ loader: fontLoader, options }) => [ + path.join(require.resolve(fontLoader), '../target.css'), + options, + ]) : undefined // Font loaders cannot be imported in _document. @@ -232,6 +231,22 @@ export const css = curry(async function css( ], }) ) + + fns.push( + loader({ + oneOf: [ + markRemovable({ + test: fontLoaderPath, + use: { + loader: 'error-loader', + options: { + reason: getFontLoaderImportError(), + }, + }, + }), + ], + }) + ) }) // CSS cannot be imported in _document. This comes before everything because diff --git a/packages/next/build/webpack/config/blocks/css/messages.ts b/packages/next/build/webpack/config/blocks/css/messages.ts index 42b5c720e54ba..b6b1b5614308e 100644 --- a/packages/next/build/webpack/config/blocks/css/messages.ts +++ b/packages/next/build/webpack/config/blocks/css/messages.ts @@ -33,7 +33,13 @@ export function getCustomDocumentError() { } export function getFontLoaderDocumentImportError() { - return `Font loaders ${chalk.bold('cannot')} be used within ${chalk.cyan( - 'pages/_document.js' - )}.` + return `Font loader error:\nFont loaders ${chalk.bold( + 'cannot' + )} be used within ${chalk.cyan('pages/_document.js')}.` +} + +export function getFontLoaderImportError() { + return `Font loader error:\nFont loaders ${chalk.bold( + 'cannot' + )} be used from within ${chalk.bold('node_modules')}.` } diff --git a/packages/next/server/config-schema.ts b/packages/next/server/config-schema.ts index b3056c4002eae..fa0e0b465b213 100644 --- a/packages/next/server/config-schema.ts +++ b/packages/next/server/config-schema.ts @@ -406,8 +406,19 @@ const configSchema = { type: 'boolean', }, fontLoaders: { - type: 'object', - }, + items: { + additionalProperties: false, + properties: { + loader: { + type: 'string', + }, + options: {}, + }, + type: 'object', + required: ['loader'], + }, + type: 'array', + } as any, webVitalsAttribution: { type: 'array', items: { diff --git a/packages/next/server/config-shared.ts b/packages/next/server/config-shared.ts index 69b1dc76914cd..56d0f3d2b203e 100644 --- a/packages/next/server/config-shared.ts +++ b/packages/next/server/config-shared.ts @@ -159,7 +159,7 @@ export interface ExperimentalConfig { // A list of packages that should be treated as external in the RSC server build serverComponentsExternalPackages?: string[] - fontLoaders?: { [fontLoader: string]: any } + fontLoaders?: [{ loader: string; options?: any }] webVitalsAttribution?: Array } diff --git a/test/e2e/app-dir/next-font/next.config.js b/test/e2e/app-dir/next-font/next.config.js index 00eafd513eb0b..447e12134a639 100644 --- a/test/e2e/app-dir/next-font/next.config.js +++ b/test/e2e/app-dir/next-font/next.config.js @@ -3,8 +3,10 @@ module.exports = { appDir: true, legacyBrowsers: false, browsersListForSwc: true, - fontLoaders: { - '@next/font/local': {}, - }, + fontLoaders: [ + { + loader: '@next/font/local', + }, + ], }, } diff --git a/test/e2e/next-font/app/next.config.js b/test/e2e/next-font/app/next.config.js index ebfb4a7678a58..6a94ea94ad864 100644 --- a/test/e2e/next-font/app/next.config.js +++ b/test/e2e/next-font/app/next.config.js @@ -1,10 +1,13 @@ module.exports = { experimental: { - fontLoaders: { - '@next/font/google': { - subsets: ['latin'], + fontLoaders: [ + { + loader: '@next/font/google', + options: { subsets: ['latin'] }, }, - '@next/font/local': {}, - }, + { + loader: '@next/font/local', + }, + ], }, } diff --git a/test/e2e/next-font/babel/next.config.js b/test/e2e/next-font/babel/next.config.js index 6cd855478a746..3f4a776b7f409 100644 --- a/test/e2e/next-font/babel/next.config.js +++ b/test/e2e/next-font/babel/next.config.js @@ -1,9 +1,10 @@ module.exports = { experimental: { - fontLoaders: { - '@next/font/google': { - subsets: ['latin'], + fontLoaders: [ + { + loader: '@next/font/google', + options: { subsets: ['latin'] }, }, - }, + ], }, } diff --git a/test/e2e/next-font/basepath/next.config.js b/test/e2e/next-font/basepath/next.config.js index 8509832e4b888..21d892f2cd5a3 100644 --- a/test/e2e/next-font/basepath/next.config.js +++ b/test/e2e/next-font/basepath/next.config.js @@ -1,10 +1,11 @@ module.exports = { basePath: '/dashboard', experimental: { - fontLoaders: { - '@next/font/google': { - subsets: ['latin'], + fontLoaders: [ + { + loader: '@next/font/google', + options: { subsets: ['latin'] }, }, - }, + ], }, } diff --git a/test/e2e/next-font/font-loader-in-document/next.config.js b/test/e2e/next-font/font-loader-in-document/next.config.js index 6cd855478a746..3f4a776b7f409 100644 --- a/test/e2e/next-font/font-loader-in-document/next.config.js +++ b/test/e2e/next-font/font-loader-in-document/next.config.js @@ -1,9 +1,10 @@ module.exports = { experimental: { - fontLoaders: { - '@next/font/google': { - subsets: ['latin'], + fontLoaders: [ + { + loader: '@next/font/google', + options: { subsets: ['latin'] }, }, - }, + ], }, } diff --git a/test/e2e/next-font/with-font-declarations-file/next.config.js b/test/e2e/next-font/with-font-declarations-file/next.config.js index ebfb4a7678a58..6a94ea94ad864 100644 --- a/test/e2e/next-font/with-font-declarations-file/next.config.js +++ b/test/e2e/next-font/with-font-declarations-file/next.config.js @@ -1,10 +1,13 @@ module.exports = { experimental: { - fontLoaders: { - '@next/font/google': { - subsets: ['latin'], + fontLoaders: [ + { + loader: '@next/font/google', + options: { subsets: ['latin'] }, }, - '@next/font/local': {}, - }, + { + loader: '@next/font/local', + }, + ], }, } diff --git a/test/e2e/next-font/without-preloaded-fonts/next.config.js b/test/e2e/next-font/without-preloaded-fonts/next.config.js index 6cd855478a746..3f4a776b7f409 100644 --- a/test/e2e/next-font/without-preloaded-fonts/next.config.js +++ b/test/e2e/next-font/without-preloaded-fonts/next.config.js @@ -1,9 +1,10 @@ module.exports = { experimental: { - fontLoaders: { - '@next/font/google': { - subsets: ['latin'], + fontLoaders: [ + { + loader: '@next/font/google', + options: { subsets: ['latin'] }, }, - }, + ], }, } From ce820e2a86a3c51550a79ab05df38ba5993e2fdc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 7 Oct 2022 15:01:02 +0200 Subject: [PATCH 10/13] Enable passing tests (#41241) --- test/e2e/app-dir/index.test.ts | 53 ++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/test/e2e/app-dir/index.test.ts b/test/e2e/app-dir/index.test.ts index 3d473a369f0ac..385cd606aa370 100644 --- a/test/e2e/app-dir/index.test.ts +++ b/test/e2e/app-dir/index.test.ts @@ -259,7 +259,7 @@ describe('app dir', () => { describe('rewrites', () => { // TODO-APP: rewrite url is broken - it.skip('should support rewrites on initial load', async () => { + it('should support rewrites on initial load', async () => { const browser = await webdriver(next.url, '/rewritten-to-dashboard') expect(await browser.elementByCss('h1').text()).toBe('Dashboard') expect(await browser.url()).toBe(`${next.url}/rewritten-to-dashboard`) @@ -826,7 +826,7 @@ describe('app dir', () => { describe('next/router', () => { // `useRouter` should not be accessible in server components. - it.skip('should always return null when accessed from /app', async () => { + it('should always return null when accessed from /app', async () => { const browser = await webdriver(next.url, '/old-router') try { @@ -1436,31 +1436,42 @@ describe('app dir', () => { }) // TODO-APP: disable failing test and investigate later - it.skip('should render the template that is a server component and rerender on navigation', async () => { - const browser = await webdriver(next.url, '/template/servercomponent') - expect(await browser.elementByCss('h1').text()).toStartWith('Template') + ;(isDev ? it.skip : it)( + 'should render the template that is a server component and rerender on navigation', + async () => { + const browser = await webdriver(next.url, '/template/servercomponent') + // eslint-disable-next-line jest/no-standalone-expect + expect(await browser.elementByCss('h1').text()).toStartWith( + 'Template' + ) - const currentTime = await browser - .elementByCss('#performance-now') - .text() + const currentTime = await browser + .elementByCss('#performance-now') + .text() - await browser.elementByCss('#link').click() - await browser.waitForElementByCss('#other-page') + await browser.elementByCss('#link').click() + await browser.waitForElementByCss('#other-page') - expect(await browser.elementByCss('h1').text()).toStartWith('Template') + // eslint-disable-next-line jest/no-standalone-expect + expect(await browser.elementByCss('h1').text()).toStartWith( + 'Template' + ) - // template should rerender on navigation even when it's a server component - expect(await browser.elementByCss('#performance-now').text()).toBe( - currentTime - ) + // template should rerender on navigation even when it's a server component + // eslint-disable-next-line jest/no-standalone-expect + expect(await browser.elementByCss('#performance-now').text()).toBe( + currentTime + ) - await browser.elementByCss('#link').click() - await browser.waitForElementByCss('#page') + await browser.elementByCss('#link').click() + await browser.waitForElementByCss('#page') - expect(await browser.elementByCss('#performance-now').text()).toBe( - currentTime - ) - }) + // eslint-disable-next-line jest/no-standalone-expect + expect(await browser.elementByCss('#performance-now').text()).toBe( + currentTime + ) + } + ) }) // TODO-APP: This is disabled for development as the error overlay needs to be reworked. From a415f34adf10c43455d4f1e5e069916a031fc7d0 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 7 Oct 2022 15:25:22 +0200 Subject: [PATCH 11/13] refactor dev overlay into hot reloader (#41231) Move react-dev-overlay into hot reloader client components, and let it imported by app router. So then we don't need to have hot reloader and react tree as adjacent sibilings but the overlay with error boundary is wrapping the react tree Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com> --- .../build/webpack/loaders/next-app-loader.ts | 6 - .../client/components/app-router.client.tsx | 43 +++---- ...t-reloader.client.tsx => hot-reloader.tsx} | 19 ++- packages/next/server/app-render.tsx | 9 +- packages/next/taskfile.js | 1 + .../src/internal/ReactDevOverlay.tsx | 109 +++++++++--------- .../src/internal/helpers/getRawSourceMap.ts | 2 +- packages/react-dev-overlay/src/middleware.ts | 7 +- pnpm-lock.yaml | 5 +- 9 files changed, 92 insertions(+), 109 deletions(-) rename packages/next/client/components/{hot-reloader.client.tsx => hot-reloader.tsx} (97%) diff --git a/packages/next/build/webpack/loaders/next-app-loader.ts b/packages/next/build/webpack/loaders/next-app-loader.ts index 473ded83103b4..f2a3c9c8980d2 100644 --- a/packages/next/build/webpack/loaders/next-app-loader.ts +++ b/packages/next/build/webpack/loaders/next-app-loader.ts @@ -185,12 +185,6 @@ const nextAppLoader: webpack.LoaderDefinitionFunction<{ export const AppRouter = require('next/dist/client/components/app-router.client.js').default export const LayoutRouter = require('next/dist/client/components/layout-router.client.js').default export const RenderFromTemplateContext = require('next/dist/client/components/render-from-template-context.client.js').default - export const HotReloader = ${ - // Disable HotReloader component in production - this.mode === 'development' - ? `require('next/dist/client/components/hot-reloader.client.js').default` - : 'null' - } export const staticGenerationAsyncStorage = require('next/dist/client/components/static-generation-async-storage.js').staticGenerationAsyncStorage export const requestAsyncStorage = require('next/dist/client/components/request-async-storage.js').requestAsyncStorage diff --git a/packages/next/client/components/app-router.client.tsx b/packages/next/client/components/app-router.client.tsx index fa6e25a6388f1..2f6daf61bf679 100644 --- a/packages/next/client/components/app-router.client.tsx +++ b/packages/next/client/components/app-router.client.tsx @@ -1,6 +1,6 @@ 'client' -import type { PropsWithChildren, ReactElement, ReactNode } from 'react' +import type { ReactNode } from 'react' import React, { useEffect, useMemo, useCallback } from 'react' import { createFromFetch } from 'next/dist/compiled/react-server-dom-webpack' import { @@ -35,6 +35,12 @@ function urlToUrlWithoutFlightMarker(url: string): URL { return urlWithoutFlightParameters } +const HotReloader: typeof import('./hot-reloader').default | null = + process.env.NODE_ENV === 'production' + ? null + : (require('./hot-reloader') + .default as typeof import('./hot-reloader').default) + /** * Fetch the flight data for the provided url. Takes in the current router state to decide what to render server-side. */ @@ -78,20 +84,6 @@ export async function fetchServerResponse( return [flightData, canonicalUrl] } -/** - * Renders development error overlay when NODE_ENV is development. - */ -function ErrorOverlay({ children }: PropsWithChildren<{}>): ReactElement { - if (process.env.NODE_ENV === 'production') { - return <>{children} - } else { - const { - ReactDevOverlay, - } = require('next/dist/compiled/@next/react-dev-overlay/dist/client') - return {children} - } -} - // Ensure the initialParallelRoutes are not combined because of double-rendering in the browser with Strict Mode. // TODO-APP: move this back into AppRouter let initialParallelRoutes: CacheNode['parallelRoutes'] = @@ -106,12 +98,12 @@ export default function AppRouter({ initialTree, initialCanonicalUrl, children, - hotReloader, + assetPrefix, }: { initialTree: FlightRouterState initialCanonicalUrl: string children: ReactNode - hotReloader?: ReactNode + assetPrefix: string }) { const initialState = useMemo(() => { return { @@ -361,16 +353,13 @@ export default function AppRouter({ url: canonicalUrl, }} > - - { - // ErrorOverlay intentionally only wraps the children of app-router. - cache.subTreeData - } - - { - // HotReloader uses the router tree and router.reload() in order to apply Server Component changes. - hotReloader - } + {HotReloader ? ( + + {cache.subTreeData} + + ) : ( + cache.subTreeData + )} diff --git a/packages/next/client/components/hot-reloader.client.tsx b/packages/next/client/components/hot-reloader.tsx similarity index 97% rename from packages/next/client/components/hot-reloader.client.tsx rename to packages/next/client/components/hot-reloader.tsx index dee184d7e1351..f03e2f62c3ef3 100644 --- a/packages/next/client/components/hot-reloader.client.tsx +++ b/packages/next/client/components/hot-reloader.tsx @@ -1,6 +1,5 @@ -'client' - -import { +import type { ReactNode } from 'react' +import React, { useCallback, useContext, useEffect, @@ -15,6 +14,7 @@ import { onBuildError, onBuildOk, onRefresh, + ReactDevOverlay, } from 'next/dist/compiled/@next/react-dev-overlay/dist/client' import stripAnsi from 'next/dist/compiled/strip-ansi' import formatWebpackMessages from '../dev/error-overlay/format-webpack-messages' @@ -398,7 +398,13 @@ function processMessage( } } -export default function HotReload({ assetPrefix }: { assetPrefix: string }) { +export default function HotReload({ + assetPrefix, + children, +}: { + assetPrefix: string + children?: ReactNode +}) { const { tree } = useContext(GlobalLayoutRouterContext) const router = useRouter() @@ -429,7 +435,7 @@ export default function HotReload({ assetPrefix }: { assetPrefix: string }) { } const { hostname, port } = window.location - const protocol = getSocketProtocol(assetPrefix || '') + const protocol = getSocketProtocol(assetPrefix) const normalizedAssetPrefix = assetPrefix.replace(/^\/+/, '') let url = `${protocol}://${hostname}:${port}${ @@ -494,5 +500,6 @@ export default function HotReload({ assetPrefix }: { assetPrefix: string }) { // return () => clearInterval(interval) // }) - return null + + return {children} } diff --git a/packages/next/server/app-render.tsx b/packages/next/server/app-render.tsx index 878805adfb123..601c94b47ce5b 100644 --- a/packages/next/server/app-render.tsx +++ b/packages/next/server/app-render.tsx @@ -810,9 +810,6 @@ export async function renderToHTMLOrFlight( ComponentMod.LayoutRouter as typeof import('../client/components/layout-router.client').default const RenderFromTemplateContext = ComponentMod.RenderFromTemplateContext as typeof import('../client/components/render-from-template-context.client').default - const HotReloader = ComponentMod.HotReloader as - | typeof import('../client/components/hot-reloader.client').default - | null /** * Server Context is specifically only available in Server Components. @@ -1373,11 +1370,7 @@ export async function renderToHTMLOrFlight( return ( - ) - } + assetPrefix={renderOpts.assetPrefix || ''} initialCanonicalUrl={initialCanonicalUrl} initialTree={initialTree} > diff --git a/packages/next/taskfile.js b/packages/next/taskfile.js index 48189b4fb91b5..cd399a37a6b23 100644 --- a/packages/next/taskfile.js +++ b/packages/next/taskfile.js @@ -1751,6 +1751,7 @@ export async function ncc_mini_css_extract_plugin(task, opts) { }) .target('compiled/mini-css-extract-plugin') } + // eslint-disable-next-line camelcase externals['ua-parser-js'] = 'next/dist/compiled/ua-parser-js' export async function ncc_ua_parser_js(task, opts) { diff --git a/packages/react-dev-overlay/src/internal/ReactDevOverlay.tsx b/packages/react-dev-overlay/src/internal/ReactDevOverlay.tsx index 21279b730bd59..707e982dcb50a 100644 --- a/packages/react-dev-overlay/src/internal/ReactDevOverlay.tsx +++ b/packages/react-dev-overlay/src/internal/ReactDevOverlay.tsx @@ -60,69 +60,68 @@ const shouldPreventDisplay = ( return preventType.includes(errorType) } -const ReactDevOverlay: React.FunctionComponent = function ReactDevOverlay({ - children, - preventDisplay, - globalOverlay, -}: { +type ReactDevOverlayProps = { children?: React.ReactNode preventDisplay?: ErrorType[] globalOverlay?: boolean -}) { - const [state, dispatch] = React.useReducer< - React.Reducer - >(reducer, { - nextId: 1, - buildError: null, - errors: [], - }) +} - React.useEffect(() => { - Bus.on(dispatch) - return function () { - Bus.off(dispatch) - } - }, [dispatch]) +const ReactDevOverlay: React.FunctionComponent = + function ReactDevOverlay({ children, preventDisplay, globalOverlay }) { + const [state, dispatch] = React.useReducer< + React.Reducer + >(reducer, { + nextId: 1, + buildError: null, + errors: [], + }) + + React.useEffect(() => { + Bus.on(dispatch) + return function () { + Bus.off(dispatch) + } + }, [dispatch]) - const onComponentError = React.useCallback( - (_error: Error, _componentStack: string | null) => { - // TODO: special handling - }, - [] - ) + const onComponentError = React.useCallback( + (_error: Error, _componentStack: string | null) => { + // TODO: special handling + }, + [] + ) - const hasBuildError = state.buildError != null - const hasRuntimeErrors = Boolean(state.errors.length) + const hasBuildError = state.buildError != null + const hasRuntimeErrors = Boolean(state.errors.length) - const isMounted = hasBuildError || hasRuntimeErrors + const isMounted = hasBuildError || hasRuntimeErrors - return ( - - - {children ?? null} - - {isMounted ? ( - - - - + return ( + + + {children ?? null} + + {isMounted ? ( + + + + - {shouldPreventDisplay( - hasBuildError ? 'build' : hasRuntimeErrors ? 'runtime' : null, - preventDisplay - ) ? null : hasBuildError ? ( - - ) : hasRuntimeErrors ? ( - - ) : undefined} - - ) : undefined} - - ) -} + {shouldPreventDisplay( + hasBuildError ? 'build' : hasRuntimeErrors ? 'runtime' : null, + preventDisplay + ) ? null : hasBuildError ? ( + + ) : hasRuntimeErrors ? ( + + ) : undefined} + + ) : undefined} + + ) + } export default ReactDevOverlay diff --git a/packages/react-dev-overlay/src/internal/helpers/getRawSourceMap.ts b/packages/react-dev-overlay/src/internal/helpers/getRawSourceMap.ts index a073a885598c1..98e09489bb58b 100644 --- a/packages/react-dev-overlay/src/internal/helpers/getRawSourceMap.ts +++ b/packages/react-dev-overlay/src/internal/helpers/getRawSourceMap.ts @@ -1,5 +1,5 @@ import dataUriToBuffer, { MimeBuffer } from 'data-uri-to-buffer' -import { RawSourceMap } from 'source-map' +import type { RawSourceMap } from 'source-map' import { getSourceMapUrl } from './getSourceMapUrl' export function getRawSourceMap(fileContents: string): RawSourceMap | null { diff --git a/packages/react-dev-overlay/src/middleware.ts b/packages/react-dev-overlay/src/middleware.ts index a3882bc2d94e2..9320a2fa84806 100644 --- a/packages/react-dev-overlay/src/middleware.ts +++ b/packages/react-dev-overlay/src/middleware.ts @@ -2,11 +2,8 @@ import { codeFrameColumns } from '@babel/code-frame' import { constants as FS, promises as fs } from 'fs' import { IncomingMessage, ServerResponse } from 'http' import path from 'path' -import { - NullableMappedPosition, - RawSourceMap, - SourceMapConsumer, -} from 'source-map' +import type { NullableMappedPosition, RawSourceMap } from 'source-map' +import { SourceMapConsumer } from 'source-map' import { StackFrame } from 'stacktrace-parser' import url from 'url' // @ts-ignore diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 183412b1d9ef6..f475b36259b09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12209,7 +12209,10 @@ packages: dev: true /css.escape/1.5.1: - resolution: { integrity: sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= } + resolution: + { + integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==, + } dev: false /css/3.0.0: From bef709bc74760aadedfeb2fd4a4434e213cb024f Mon Sep 17 00:00:00 2001 From: Damien Simonin Feugas Date: Fri, 7 Oct 2022 16:14:11 +0200 Subject: [PATCH 12/13] fix(middleware): 'instanceof Function' is dynamic code false-positive (#41249) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## ๐Ÿ› What's in there? `foo instanceof Function` is wrongly considered as Dynamic code evaluation by our static analyzer. This PR fixes it. - [ ] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Errors have a helpful link attached, see `contributing.md` ## ๐Ÿงช How to reproduce? 1. Create a simple repro in `examples` folder: ```js // examples/instance-of-function/pages/index.js export default function Home() { return

home

} // examples/instance-of-function/middleware.js import { NextResponse } from 'next/server' export default async function handler() { console.log('is arrow a function?', (() => {}) instanceof Function) return NextResponse.next() } ``` 1. build with next `pnpm next build examples/instance-of-function` > the build fails 1. rebuild next to include PR's fix `pnpm build` 1. build with new next `pnpm next build examples/instance-of-function` > the build works ## ๐Ÿ“” Notes to reviewers `hooks.expression.for(`${prefix}Function`).tap(NAME, handleExpression)` is actually legacy code from the original implementation. It's used when finding `Function` regardless of how it is used. We only want to find `new Function()` or `Function()`, which `hooks.calls` and `hooks.new` are covering. `eval instanceof Function` is perfectly legit code on the edge, despite its uselessness :lol-think: Because we got multiple people asking "how do I relax this error when my code contains unreachable dynamic code evaluation", I've copy-pasted details about `config.unstable_allowDynamic` into the error page. Because users do not always click links :blob_shrug: --- errors/edge-dynamic-code-evaluation.md | 14 ++++- .../webpack/plugins/middleware-plugin.ts | 2 - .../test/index.test.js | 57 +++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/errors/edge-dynamic-code-evaluation.md b/errors/edge-dynamic-code-evaluation.md index 29a5e74b6329f..26a2de05ef172 100644 --- a/errors/edge-dynamic-code-evaluation.md +++ b/errors/edge-dynamic-code-evaluation.md @@ -29,6 +29,18 @@ export default async function middleware() { ``` In rare cases, your code could contain (or import) some dynamic code evaluation statements which _can not be reached at runtime_ and which can not be removed by treeshaking. -You can relax the check to allow specific files with your Middleware or Edge API Route exported [configuration](https://nextjs.org/docs/api-reference/edge-runtime#unsupported-apis). +You can relax the check to allow specific files with your Middleware or Edge API Route exported [configuration](https://nextjs.org/docs/api-reference/edge-runtime#unsupported-apis): + +```typescript +export const config = { + runtime: 'experimental-edge', // for Edge API Routes only + unstable_allowDynamic: [ + '/lib/utilities.js', // allows a single file + '/node_modules/function-bind/**', // use a glob to allow anything in the function-bind 3rd party module + ], +} +``` + +`unstable_allowDynamic` is a glob, or an array of globs, ignoring dynamic code evaluation for specific files. The globs are relative to your application root folder. Be warned that if these statements are executed on the Edge, _they will throw and cause a runtime error_. diff --git a/packages/next/build/webpack/plugins/middleware-plugin.ts b/packages/next/build/webpack/plugins/middleware-plugin.ts index e0e206bb11541..5c100ec15b196 100644 --- a/packages/next/build/webpack/plugins/middleware-plugin.ts +++ b/packages/next/build/webpack/plugins/middleware-plugin.ts @@ -553,8 +553,6 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`, hooks.call.for(`${prefix}eval`).tap(NAME, handleWrapExpression) hooks.call.for(`${prefix}Function`).tap(NAME, handleWrapExpression) hooks.new.for(`${prefix}Function`).tap(NAME, handleWrapExpression) - hooks.expression.for(`${prefix}eval`).tap(NAME, handleExpression) - hooks.expression.for(`${prefix}Function`).tap(NAME, handleExpression) hooks.call .for(`${prefix}WebAssembly.compile`) .tap(NAME, handleWrapWasmCompileExpression) diff --git a/test/integration/edge-runtime-configurable-guards/test/index.test.js b/test/integration/edge-runtime-configurable-guards/test/index.test.js index bc218a0f03265..c55c813b4a8f0 100644 --- a/test/integration/edge-runtime-configurable-guards/test/index.test.js +++ b/test/integration/edge-runtime-configurable-guards/test/index.test.js @@ -387,4 +387,61 @@ describe('Edge runtime configurable guards', () => { expect(output.stderr).toContain(TELEMETRY_EVENT_NAME) }) }) + + describe.each([ + { + title: 'Edge API', + url: routeUrl, + init() { + context.api.write(` + export default async function handler(request) { + return Response.json({ result: (() => {}) instanceof Function }) + } + export const config = { runtime: 'experimental-edge' } + `) + }, + }, + { + title: 'Middleware', + url: middlewareUrl, + init() { + context.middleware.write(` + import { NextResponse } from 'next/server' + import { returnTrue } from './lib' + export default async function () { + (() => {}) instanceof Function + return NextResponse.next() + } + `) + }, + }, + ])('$title with use of Function as a type', ({ init, url }) => { + beforeEach(() => init()) + + it('does not warn in dev at runtime', async () => { + context.app = await launchApp(context.appDir, context.appPort, appOption) + const res = await fetchViaHTTP(context.appPort, url) + await waitFor(500) + expect(res.status).toBe(200) + expect(context.logs.output).not.toContain( + `Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Edge Runtime` + ) + }) + + // eslint-disable-next-line jest/no-identical-title + it('build and does not warn at runtime', async () => { + const output = await nextBuild(context.appDir, undefined, { + stdout: true, + stderr: true, + }) + expect(output.stderr).not.toContain(`Build failed`) + context.app = await nextStart(context.appDir, context.appPort, appOption) + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(200) + expect(context.logs.output).not.toContain(`warn`) + expect(context.logs.output).not.toContain( + `Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Edge Runtime` + ) + }) + }) }) From eb629c15ca55c247d216963a16abc1bea60d7f91 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 7 Oct 2022 18:57:22 +0200 Subject: [PATCH 13/13] Skip serverless/serverless-trace target tests (#41252) --- test/integration/404-page-custom-error/test/index.test.js | 2 +- test/integration/404-page-ssg/test/index.test.js | 2 +- test/integration/404-page/test/index.test.js | 2 +- test/integration/500-page/test/index.test.js | 2 +- test/integration/amphtml-ssg/test/index.test.js | 2 +- test/integration/api-catch-all/test/index.test.js | 2 +- test/integration/api-support/test/index.test.js | 2 +- test/integration/app-tree/test/index.test.js | 2 +- test/integration/async-modules/test/index.test.js | 2 +- test/integration/auto-export-error-bail/test/index.test.js | 2 +- test/integration/auto-export-query-error/test/index.test.js | 2 +- .../auto-export-serverless-error/test/index.test.js | 2 +- test/integration/auto-export-serverless/test/index.test.js | 2 +- test/integration/basepath-root-catch-all/test/index.test.js | 2 +- test/integration/bigint/test/index.test.js | 2 +- test/integration/clean-distdir/test/index.test.js | 2 +- test/integration/critical-css/test/index.test.js | 2 +- test/integration/custom-error/test/index.test.js | 2 +- test/integration/custom-page-extension/test/index.test.js | 2 +- test/integration/custom-routes/test/index.test.js | 4 ++-- .../test/index.test.js | 2 +- .../test/index.test.js | 2 +- .../integration/dynamic-optional-routing/test/index.test.js | 4 ++-- test/integration/env-config/test/index.test.js | 2 +- test/integration/fallback-route-params/test/index.test.js | 2 +- .../fetch-polyfill-ky-universal/test/index.test.js | 2 +- test/integration/fetch-polyfill/test/index.test.js | 2 +- test/integration/font-optimization/test/index.test.js | 4 ++-- test/integration/getinitialprops/test/index.test.js | 2 +- .../getserversideprops-export-error/test/index.test.js | 2 +- .../getserversideprops-preview/test/index.test.js | 4 ++-- test/integration/gssp-pageProps-merge/test/index.test.js | 2 +- test/integration/gssp-redirect-base-path/test/index.test.js | 2 +- test/integration/gssp-redirect/test/index.test.js | 2 +- .../integration/handle-non-page-in-pages/test/index.test.js | 2 +- test/integration/i18n-support-base-path/test/index.test.js | 2 +- test/integration/i18n-support-catchall/test/index.test.js | 2 +- test/integration/i18n-support/test/index.test.js | 2 +- .../image-component/base-path/test/index.test.ts | 2 +- test/integration/image-component/default/test/index.test.ts | 2 +- test/integration/index-index/test/index.test.js | 2 +- .../integration/legacy-ssg-methods-error/test/index.test.js | 2 +- .../optional-chaining-nullish-coalescing/test/index.test.js | 2 +- test/integration/prerender-no-revalidate/test/index.test.js | 2 +- test/integration/prerender-preview/test/index.test.js | 4 ++-- test/integration/preview-fallback/test/index.test.js | 2 +- .../production-browser-sourcemaps/test/index.test.js | 2 +- test/integration/revalidate-as-path/test/index.test.js | 2 +- .../integration/root-optional-revalidate/test/index.test.js | 2 +- test/integration/server-asset-modules/test/index.test.js | 2 +- .../serverless-runtime-configs/test/index.test.js | 6 +++--- .../serverless-trace-revalidate/test/index.test.js | 2 +- test/integration/serverless-trace/test/index.test.js | 2 +- test/integration/serverless/test/index.test.js | 2 +- .../src-dir-support-double-dir/test/index.test.js | 2 +- .../ssg-dynamic-routes-404-page/test/index.test.js | 2 +- test/integration/static-page-name/test/index.test.js | 2 +- .../index.test.ts | 2 +- 58 files changed, 65 insertions(+), 65 deletions(-) diff --git a/test/integration/404-page-custom-error/test/index.test.js b/test/integration/404-page-custom-error/test/index.test.js index a962ada95d3a9..26e767a65c7dc 100644 --- a/test/integration/404-page-custom-error/test/index.test.js +++ b/test/integration/404-page-custom-error/test/index.test.js @@ -71,7 +71,7 @@ describe('Default 404 Page with custom _error', () => { runTests('server') }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { afterAll(async () => { await fs.remove(nextConfig) await killApp(app) diff --git a/test/integration/404-page-ssg/test/index.test.js b/test/integration/404-page-ssg/test/index.test.js index af8cef3e23f60..10db743e90c3b 100644 --- a/test/integration/404-page-ssg/test/index.test.js +++ b/test/integration/404-page-ssg/test/index.test.js @@ -114,7 +114,7 @@ describe('404 Page Support SSG', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { afterAll(async () => { await fs.writeFile(nextConfig, nextConfigContent) await killApp(app) diff --git a/test/integration/404-page/test/index.test.js b/test/integration/404-page/test/index.test.js index a5df93cceec57..e2e6d2e5eb7bf 100644 --- a/test/integration/404-page/test/index.test.js +++ b/test/integration/404-page/test/index.test.js @@ -92,7 +92,7 @@ describe('404 Page Support', () => { runTests('server') }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { nextConfigContent = await fs.readFile(nextConfig, 'utf8') await fs.writeFile( diff --git a/test/integration/500-page/test/index.test.js b/test/integration/500-page/test/index.test.js index bf5bea2f30f5a..04e341354303c 100644 --- a/test/integration/500-page/test/index.test.js +++ b/test/integration/500-page/test/index.test.js @@ -85,7 +85,7 @@ describe('500 Page Support', () => { runTests('server') }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { nextConfigContent = await fs.readFile(nextConfig, 'utf8') await fs.writeFile( diff --git a/test/integration/amphtml-ssg/test/index.test.js b/test/integration/amphtml-ssg/test/index.test.js index 7938e567e9344..550543a7ede43 100644 --- a/test/integration/amphtml-ssg/test/index.test.js +++ b/test/integration/amphtml-ssg/test/index.test.js @@ -99,7 +99,7 @@ const runTests = (isDev = false) => { } describe('AMP SSG Support', () => { - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/api-catch-all/test/index.test.js b/test/integration/api-catch-all/test/index.test.js index 86e5308c4926a..ce96d97e357b5 100644 --- a/test/integration/api-catch-all/test/index.test.js +++ b/test/integration/api-catch-all/test/index.test.js @@ -73,7 +73,7 @@ describe('API routes', () => { runTests() }) - describe('Serverless support', () => { + describe.skip('Serverless support', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/api-support/test/index.test.js b/test/integration/api-support/test/index.test.js index 66953223aa2a7..30ba7f9513f78 100644 --- a/test/integration/api-support/test/index.test.js +++ b/test/integration/api-support/test/index.test.js @@ -620,7 +620,7 @@ describe('API routes', () => { runTests() }) - describe('Serverless support', () => { + describe.skip('Serverless support', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/app-tree/test/index.test.js b/test/integration/app-tree/test/index.test.js index 10d0599697599..35a8a506ad8c9 100644 --- a/test/integration/app-tree/test/index.test.js +++ b/test/integration/app-tree/test/index.test.js @@ -69,7 +69,7 @@ describe('AppTree', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/async-modules/test/index.test.js b/test/integration/async-modules/test/index.test.js index 7a7d4efd790e0..cdae323f56e9c 100644 --- a/test/integration/async-modules/test/index.test.js +++ b/test/integration/async-modules/test/index.test.js @@ -131,7 +131,7 @@ describe('Async modules', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { nextConfig.replace('// target:', 'target:') await nextBuild(appDir) diff --git a/test/integration/auto-export-error-bail/test/index.test.js b/test/integration/auto-export-error-bail/test/index.test.js index b4329f4206389..ebba608acd548 100644 --- a/test/integration/auto-export-error-bail/test/index.test.js +++ b/test/integration/auto-export-error-bail/test/index.test.js @@ -36,7 +36,7 @@ describe('Auto Export _error bail', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(() => fs.writeFile( nextConfig, diff --git a/test/integration/auto-export-query-error/test/index.test.js b/test/integration/auto-export-query-error/test/index.test.js index dfc3774d387b5..696f9b725c685 100644 --- a/test/integration/auto-export-query-error/test/index.test.js +++ b/test/integration/auto-export-query-error/test/index.test.js @@ -41,7 +41,7 @@ describe('Auto Export', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { origNextConfig = await fs.readFile(nextConfig, 'utf8') await nextBuild(appDir) diff --git a/test/integration/auto-export-serverless-error/test/index.test.js b/test/integration/auto-export-serverless-error/test/index.test.js index d18d283d7f024..3e12333ba53c7 100644 --- a/test/integration/auto-export-serverless-error/test/index.test.js +++ b/test/integration/auto-export-serverless-error/test/index.test.js @@ -6,7 +6,7 @@ import { nextBuild } from 'next-test-utils' const appDir = path.join(__dirname, '..') -describe('Auto Export Error Serverless', () => { +describe.skip('Auto Export Error Serverless', () => { it('fails to emit the page', async () => { const { stderr } = await nextBuild(appDir, [], { stderr: true, diff --git a/test/integration/auto-export-serverless/test/index.test.js b/test/integration/auto-export-serverless/test/index.test.js index 4870ed9d4ab97..bc170fe8249d8 100644 --- a/test/integration/auto-export-serverless/test/index.test.js +++ b/test/integration/auto-export-serverless/test/index.test.js @@ -8,7 +8,7 @@ const appDir = path.join(__dirname, '..') let appPort let app -describe('Auto Export Serverless', () => { +describe.skip('Auto Export Serverless', () => { it('Refreshes query on mount', async () => { await nextBuild(appDir) appPort = await findPort() diff --git a/test/integration/basepath-root-catch-all/test/index.test.js b/test/integration/basepath-root-catch-all/test/index.test.js index 0d66c5dfae708..0c41258387e63 100644 --- a/test/integration/basepath-root-catch-all/test/index.test.js +++ b/test/integration/basepath-root-catch-all/test/index.test.js @@ -51,7 +51,7 @@ describe('production mode', () => { runTests() }) -describe('serverless mode', () => { +describe.skip('serverless mode', () => { beforeAll(async () => { nextConfig.replace('// target', 'target') await nextBuild(appDir) diff --git a/test/integration/bigint/test/index.test.js b/test/integration/bigint/test/index.test.js index 514037af1d123..51a57c232559f 100644 --- a/test/integration/bigint/test/index.test.js +++ b/test/integration/bigint/test/index.test.js @@ -55,7 +55,7 @@ describe('bigint API route support', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/clean-distdir/test/index.test.js b/test/integration/clean-distdir/test/index.test.js index a6759dd52fe01..3d0e70c5e9af4 100644 --- a/test/integration/clean-distdir/test/index.test.js +++ b/test/integration/clean-distdir/test/index.test.js @@ -33,7 +33,7 @@ describe('Cleaning distDir', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { nextConfigContent = await fs.readFile(nextConfig, 'utf8') await fs.writeFile( diff --git a/test/integration/critical-css/test/index.test.js b/test/integration/critical-css/test/index.test.js index 2c1469866c4c4..f0b4aeb831cb5 100644 --- a/test/integration/critical-css/test/index.test.js +++ b/test/integration/critical-css/test/index.test.js @@ -78,7 +78,7 @@ describe('CSS optimization for SSR apps', () => { runTests() }) -describe('Font optimization for emulated serverless apps', () => { +describe.skip('Font optimization for emulated serverless apps', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/custom-error/test/index.test.js b/test/integration/custom-error/test/index.test.js index e2cc0488846f2..d3fa642ed5545 100644 --- a/test/integration/custom-error/test/index.test.js +++ b/test/integration/custom-error/test/index.test.js @@ -103,7 +103,7 @@ describe('Custom _error', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/custom-page-extension/test/index.test.js b/test/integration/custom-page-extension/test/index.test.js index 5221e2a9078f2..5471699a83c6d 100644 --- a/test/integration/custom-page-extension/test/index.test.js +++ b/test/integration/custom-page-extension/test/index.test.js @@ -47,7 +47,7 @@ describe('Custom page extension', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { const nextConfig = new File(join(appDir, 'next.config.js')) beforeAll(async () => { nextConfig.replace('server', 'serverless') diff --git a/test/integration/custom-routes/test/index.test.js b/test/integration/custom-routes/test/index.test.js index 885683cc40be9..673e5ea34f37d 100644 --- a/test/integration/custom-routes/test/index.test.js +++ b/test/integration/custom-routes/test/index.test.js @@ -2426,7 +2426,7 @@ describe('Custom routes', () => { }) }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { nextConfigContent = await fs.readFile(nextConfigPath, 'utf8') await fs.writeFile( @@ -2454,7 +2454,7 @@ describe('Custom routes', () => { runTests() }) - describe('raw serverless mode', () => { + describe.skip('raw serverless mode', () => { beforeAll(async () => { nextConfigContent = await fs.readFile(nextConfigPath, 'utf8') await fs.writeFile( diff --git a/test/integration/dynamic-optional-routing-root-fallback/test/index.test.js b/test/integration/dynamic-optional-routing-root-fallback/test/index.test.js index 53c38501d0a76..0454e0c143766 100644 --- a/test/integration/dynamic-optional-routing-root-fallback/test/index.test.js +++ b/test/integration/dynamic-optional-routing-root-fallback/test/index.test.js @@ -82,7 +82,7 @@ describe('Dynamic Optional Routing Root Fallback', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let origNextConfig beforeAll(async () => { diff --git a/test/integration/dynamic-optional-routing-root-static-paths/test/index.test.js b/test/integration/dynamic-optional-routing-root-static-paths/test/index.test.js index 47f07e894c553..05ebed2c19515 100644 --- a/test/integration/dynamic-optional-routing-root-static-paths/test/index.test.js +++ b/test/integration/dynamic-optional-routing-root-static-paths/test/index.test.js @@ -66,7 +66,7 @@ describe('Dynamic Optional Routing', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let origNextConfig beforeAll(async () => { diff --git a/test/integration/dynamic-optional-routing/test/index.test.js b/test/integration/dynamic-optional-routing/test/index.test.js index 8d8b896df6004..84343a283acaa 100644 --- a/test/integration/dynamic-optional-routing/test/index.test.js +++ b/test/integration/dynamic-optional-routing/test/index.test.js @@ -314,7 +314,7 @@ describe('Dynamic Optional Routing', () => { }) }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let origNextConfig beforeAll(async () => { @@ -336,7 +336,7 @@ describe('Dynamic Optional Routing', () => { runTests() }) - describe('raw serverless mode', () => { + describe.skip('raw serverless mode', () => { let origNextConfig beforeAll(async () => { diff --git a/test/integration/env-config/test/index.test.js b/test/integration/env-config/test/index.test.js index 6846e9e2f24f4..f6c0571ede8db 100644 --- a/test/integration/env-config/test/index.test.js +++ b/test/integration/env-config/test/index.test.js @@ -385,7 +385,7 @@ describe('Env Config', () => { runTests('server') }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let nextConfigContent = '' const nextConfigPath = join(appDir, 'next.config.js') const envFiles = [ diff --git a/test/integration/fallback-route-params/test/index.test.js b/test/integration/fallback-route-params/test/index.test.js index 06be7076b3fda..04f04b2f6738c 100644 --- a/test/integration/fallback-route-params/test/index.test.js +++ b/test/integration/fallback-route-params/test/index.test.js @@ -65,7 +65,7 @@ describe('Fallback Dynamic Route Params', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { nextConfig.write(` module.exports = { diff --git a/test/integration/fetch-polyfill-ky-universal/test/index.test.js b/test/integration/fetch-polyfill-ky-universal/test/index.test.js index 5c54ac7eeca5f..681dd5da6d271 100644 --- a/test/integration/fetch-polyfill-ky-universal/test/index.test.js +++ b/test/integration/fetch-polyfill-ky-universal/test/index.test.js @@ -104,7 +104,7 @@ describe('Fetch polyfill with ky-universal', () => { runTests() }) - describe('Serverless support', () => { + describe.skip('Serverless support', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/fetch-polyfill/test/index.test.js b/test/integration/fetch-polyfill/test/index.test.js index a0aa4cd19e21b..0e5b5f6712e8a 100644 --- a/test/integration/fetch-polyfill/test/index.test.js +++ b/test/integration/fetch-polyfill/test/index.test.js @@ -123,7 +123,7 @@ describe('Fetch polyfill', () => { runTests() }) - describe('Serverless support', () => { + describe.skip('Serverless support', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/font-optimization/test/index.test.js b/test/integration/font-optimization/test/index.test.js index bf2833e72142d..93e080d79dd0b 100644 --- a/test/integration/font-optimization/test/index.test.js +++ b/test/integration/font-optimization/test/index.test.js @@ -250,7 +250,7 @@ describe('Font Optimization', () => { runTests() }) - describe('Font optimization for serverless apps', () => { + describe.skip('Font optimization for serverless apps', () => { const origNextConfig = fs.readFileSync(nextConfig) beforeAll(async () => { @@ -272,7 +272,7 @@ describe('Font Optimization', () => { runTests() }) - describe('Font optimization for emulated serverless apps', () => { + describe.skip('Font optimization for emulated serverless apps', () => { const origNextConfig = fs.readFileSync(nextConfig) beforeAll(async () => { diff --git a/test/integration/getinitialprops/test/index.test.js b/test/integration/getinitialprops/test/index.test.js index 2398120a3393a..6f748b680879a 100644 --- a/test/integration/getinitialprops/test/index.test.js +++ b/test/integration/getinitialprops/test/index.test.js @@ -52,7 +52,7 @@ describe('getInitialProps', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await nextConfig.replace('// replace me', `target: 'serverless', `) await nextBuild(appDir) diff --git a/test/integration/getserversideprops-export-error/test/index.test.js b/test/integration/getserversideprops-export-error/test/index.test.js index 5046ee814f3d0..dc5f70bf21efb 100644 --- a/test/integration/getserversideprops-export-error/test/index.test.js +++ b/test/integration/getserversideprops-export-error/test/index.test.js @@ -29,7 +29,7 @@ const runTests = () => { } describe('getServerSideProps', () => { - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.remove(join(appDir, '.next')) await fs.writeFile( diff --git a/test/integration/getserversideprops-preview/test/index.test.js b/test/integration/getserversideprops-preview/test/index.test.js index b3ec85122f959..18026f4ded946 100644 --- a/test/integration/getserversideprops-preview/test/index.test.js +++ b/test/integration/getserversideprops-preview/test/index.test.js @@ -294,7 +294,7 @@ describe('ServerSide Props Preview Mode', () => { runTests() }) - describe('Serverless Mode', () => { + describe.skip('Serverless Mode', () => { beforeAll(async () => { await fs.writeFile( nextConfigPath, @@ -308,7 +308,7 @@ describe('ServerSide Props Preview Mode', () => { runTests() }) - describe('Emulated Serverless Mode', () => { + describe.skip('Emulated Serverless Mode', () => { beforeAll(async () => { await fs.writeFile( nextConfigPath, diff --git a/test/integration/gssp-pageProps-merge/test/index.test.js b/test/integration/gssp-pageProps-merge/test/index.test.js index a9a7716332987..840f96a6ae858 100644 --- a/test/integration/gssp-pageProps-merge/test/index.test.js +++ b/test/integration/gssp-pageProps-merge/test/index.test.js @@ -56,7 +56,7 @@ describe('pageProps GSSP conflict', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/gssp-redirect-base-path/test/index.test.js b/test/integration/gssp-redirect-base-path/test/index.test.js index 8fb4dbb7c944f..fe309d0d6b896 100644 --- a/test/integration/gssp-redirect-base-path/test/index.test.js +++ b/test/integration/gssp-redirect-base-path/test/index.test.js @@ -505,7 +505,7 @@ describe('GS(S)P Redirect Support', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let server beforeAll(async () => { diff --git a/test/integration/gssp-redirect/test/index.test.js b/test/integration/gssp-redirect/test/index.test.js index 009463b63bd81..548f9d8ea43a3 100644 --- a/test/integration/gssp-redirect/test/index.test.js +++ b/test/integration/gssp-redirect/test/index.test.js @@ -542,7 +542,7 @@ describe('GS(S)P Redirect Support', () => { }) }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let server beforeAll(async () => { diff --git a/test/integration/handle-non-page-in-pages/test/index.test.js b/test/integration/handle-non-page-in-pages/test/index.test.js index cefe5e320c729..3254cc2a7dcd1 100644 --- a/test/integration/handle-non-page-in-pages/test/index.test.js +++ b/test/integration/handle-non-page-in-pages/test/index.test.js @@ -5,7 +5,7 @@ import { nextBuild } from 'next-test-utils' const appDir = path.join(__dirname, '..') -describe('Handle non-page in pages when target: serverless', () => { +describe.skip('Handle non-page in pages when target: serverless', () => { it('Fails softly with descriptive error', async () => { const { stderr } = await nextBuild(appDir, [], { stderr: true }) diff --git a/test/integration/i18n-support-base-path/test/index.test.js b/test/integration/i18n-support-base-path/test/index.test.js index 4ce30b352bc49..5ee93bd72057a 100644 --- a/test/integration/i18n-support-base-path/test/index.test.js +++ b/test/integration/i18n-support-base-path/test/index.test.js @@ -72,7 +72,7 @@ describe('i18n Support basePath', () => { runTests(ctx) }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.remove(join(appDir, '.next')) nextConfig.replace('// target', 'target') diff --git a/test/integration/i18n-support-catchall/test/index.test.js b/test/integration/i18n-support-catchall/test/index.test.js index 2f06e67d2edf4..6b3aadc60e8ec 100644 --- a/test/integration/i18n-support-catchall/test/index.test.js +++ b/test/integration/i18n-support-catchall/test/index.test.js @@ -250,7 +250,7 @@ describe('i18n Support Root Catch-all', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.remove(join(appDir, '.next')) nextConfig.replace('// target', 'target') diff --git a/test/integration/i18n-support/test/index.test.js b/test/integration/i18n-support/test/index.test.js index b0dedd2034c8b..6bf502d668ab4 100644 --- a/test/integration/i18n-support/test/index.test.js +++ b/test/integration/i18n-support/test/index.test.js @@ -89,7 +89,7 @@ describe('i18n Support', () => { }) }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.remove(join(appDir, '.next')) nextConfig.replace('// target', 'target') diff --git a/test/integration/image-component/base-path/test/index.test.ts b/test/integration/image-component/base-path/test/index.test.ts index e85b1e3f3a8df..0273044bfa689 100644 --- a/test/integration/image-component/base-path/test/index.test.ts +++ b/test/integration/image-component/base-path/test/index.test.ts @@ -505,7 +505,7 @@ describe('Image Component basePath Tests', () => { runTests('server') }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let origConfig beforeAll(async () => { diff --git a/test/integration/image-component/default/test/index.test.ts b/test/integration/image-component/default/test/index.test.ts index c92422a74413f..2fe202645dff4 100644 --- a/test/integration/image-component/default/test/index.test.ts +++ b/test/integration/image-component/default/test/index.test.ts @@ -1447,7 +1447,7 @@ describe('Image Component Tests', () => { runTests('server') }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await nextBuild(appDir) appPort = await findPort() diff --git a/test/integration/index-index/test/index.test.js b/test/integration/index-index/test/index.test.js index 21baf93f00ec1..a2d7bfa8e3f16 100644 --- a/test/integration/index-index/test/index.test.js +++ b/test/integration/index-index/test/index.test.js @@ -209,7 +209,7 @@ describe('nested index.js', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let origNextConfig beforeAll(async () => { diff --git a/test/integration/legacy-ssg-methods-error/test/index.test.js b/test/integration/legacy-ssg-methods-error/test/index.test.js index b562b6c05b2a7..90d83c8157f16 100644 --- a/test/integration/legacy-ssg-methods-error/test/index.test.js +++ b/test/integration/legacy-ssg-methods-error/test/index.test.js @@ -73,7 +73,7 @@ describe('Mixed getStaticProps and getServerSideProps error', () => { runTests(false) }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { runTests(true) }) }) diff --git a/test/integration/optional-chaining-nullish-coalescing/test/index.test.js b/test/integration/optional-chaining-nullish-coalescing/test/index.test.js index 3534c5f460774..79681cdac6789 100644 --- a/test/integration/optional-chaining-nullish-coalescing/test/index.test.js +++ b/test/integration/optional-chaining-nullish-coalescing/test/index.test.js @@ -53,7 +53,7 @@ describe('Optional chaining and nullish coalescing support', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/prerender-no-revalidate/test/index.test.js b/test/integration/prerender-no-revalidate/test/index.test.js index 73c42a4143efa..a02f9c2a5c3f0 100644 --- a/test/integration/prerender-no-revalidate/test/index.test.js +++ b/test/integration/prerender-no-revalidate/test/index.test.js @@ -79,7 +79,7 @@ function runTests(route, routePath, serverless) { describe('SSG Prerender No Revalidate', () => { afterAll(() => fs.remove(nextConfig)) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/prerender-preview/test/index.test.js b/test/integration/prerender-preview/test/index.test.js index c27b0c59fff11..67b803a14e46d 100644 --- a/test/integration/prerender-preview/test/index.test.js +++ b/test/integration/prerender-preview/test/index.test.js @@ -405,7 +405,7 @@ describe('Prerender Preview Mode', () => { runTests() }) - describe('Serverless Mode', () => { + describe.skip('Serverless Mode', () => { beforeAll(async () => { await fs.writeFile( nextConfigPath, @@ -419,7 +419,7 @@ describe('Prerender Preview Mode', () => { runTests() }) - describe('Emulated Serverless Mode', () => { + describe.skip('Emulated Serverless Mode', () => { beforeAll(async () => { await fs.writeFile( nextConfigPath, diff --git a/test/integration/preview-fallback/test/index.test.js b/test/integration/preview-fallback/test/index.test.js index 66389ff30b1c6..26fa8f17e60da 100644 --- a/test/integration/preview-fallback/test/index.test.js +++ b/test/integration/preview-fallback/test/index.test.js @@ -303,7 +303,7 @@ describe('Preview mode with fallback pages', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { nextConfig.write(` module.exports = { diff --git a/test/integration/production-browser-sourcemaps/test/index.test.js b/test/integration/production-browser-sourcemaps/test/index.test.js index 202525d0dedf4..b9e1e7da647f8 100644 --- a/test/integration/production-browser-sourcemaps/test/index.test.js +++ b/test/integration/production-browser-sourcemaps/test/index.test.js @@ -51,7 +51,7 @@ describe('Production browser sourcemaps', () => { runTests() }) - describe('Serverless support', () => { + describe.skip('Serverless support', () => { beforeAll(async () => { nextConfigContent = await fs.readFile(nextConfig, 'utf8') await fs.writeFile( diff --git a/test/integration/revalidate-as-path/test/index.test.js b/test/integration/revalidate-as-path/test/index.test.js index 5c06e1af2e72f..0bd089943d203 100644 --- a/test/integration/revalidate-as-path/test/index.test.js +++ b/test/integration/revalidate-as-path/test/index.test.js @@ -78,7 +78,7 @@ const runTests = (isServerless) => { } describe('Revalidate asPath Normalizing', () => { - describe('raw serverless mode', () => { + describe.skip('raw serverless mode', () => { beforeAll(async () => { await fs.remove(join(appDir, '.next')) await fs.writeFile( diff --git a/test/integration/root-optional-revalidate/test/index.test.js b/test/integration/root-optional-revalidate/test/index.test.js index 9ec56a7e19d77..bf69ff160ec1b 100644 --- a/test/integration/root-optional-revalidate/test/index.test.js +++ b/test/integration/root-optional-revalidate/test/index.test.js @@ -88,7 +88,7 @@ describe('Root Optional Catch-all Revalidate', () => { runTests() }) - describe('raw serverless mode', () => { + describe.skip('raw serverless mode', () => { beforeAll(async () => { nextConfig.write(` module.exports = { diff --git a/test/integration/server-asset-modules/test/index.test.js b/test/integration/server-asset-modules/test/index.test.js index c52d05d7928b8..f6e4fda5e3dee 100644 --- a/test/integration/server-asset-modules/test/index.test.js +++ b/test/integration/server-asset-modules/test/index.test.js @@ -56,7 +56,7 @@ describe('serverside asset modules', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { let origNextConfig beforeAll(async () => { diff --git a/test/integration/serverless-runtime-configs/test/index.test.js b/test/integration/serverless-runtime-configs/test/index.test.js index c380055bf0250..eb29238ea5baf 100644 --- a/test/integration/serverless-runtime-configs/test/index.test.js +++ b/test/integration/serverless-runtime-configs/test/index.test.js @@ -166,15 +166,15 @@ const runTests = (oldServerless = false) => { }) } -describe('Serverless runtime configs', () => { +describe.skip('Serverless runtime configs', () => { beforeAll(() => cleanUp()) afterAll(() => cleanUp()) - describe('legacy serverless mode', () => { + describe.skip('legacy serverless mode', () => { runTests(true) }) - describe('experimental-serverless-trace mode', () => { + describe.skip('experimental-serverless-trace mode', () => { runTests() }) }) diff --git a/test/integration/serverless-trace-revalidate/test/index.test.js b/test/integration/serverless-trace-revalidate/test/index.test.js index 11f0dc0f84c80..d258b8f062405 100644 --- a/test/integration/serverless-trace-revalidate/test/index.test.js +++ b/test/integration/serverless-trace-revalidate/test/index.test.js @@ -27,7 +27,7 @@ const nextStart = async (appDir, appPort) => { ) } -describe('Serverless Trace', () => { +describe.skip('Serverless Trace', () => { beforeAll(async () => { await nextBuild(appDir) appPort = await findPort() diff --git a/test/integration/serverless-trace/test/index.test.js b/test/integration/serverless-trace/test/index.test.js index 8631f77fb45ed..bfbdb8ca08a6f 100644 --- a/test/integration/serverless-trace/test/index.test.js +++ b/test/integration/serverless-trace/test/index.test.js @@ -21,7 +21,7 @@ const chunksDir = join(appDir, '.next/static/chunks') let appPort let app -describe('Serverless Trace', () => { +describe.skip('Serverless Trace', () => { beforeAll(async () => { await nextBuild(appDir) appPort = await findPort() diff --git a/test/integration/serverless/test/index.test.js b/test/integration/serverless/test/index.test.js index 60871c2e86022..d41cc66e93eb4 100644 --- a/test/integration/serverless/test/index.test.js +++ b/test/integration/serverless/test/index.test.js @@ -25,7 +25,7 @@ let stderr = '' let appPort let app -describe('Serverless', () => { +describe.skip('Serverless', () => { let output beforeAll(async () => { diff --git a/test/integration/src-dir-support-double-dir/test/index.test.js b/test/integration/src-dir-support-double-dir/test/index.test.js index 5d4f791fda915..3b8bd37406673 100644 --- a/test/integration/src-dir-support-double-dir/test/index.test.js +++ b/test/integration/src-dir-support-double-dir/test/index.test.js @@ -57,7 +57,7 @@ describe('Dynamic Routing', () => { runTests() }) - describe('serverless production mode', () => { + describe.skip('serverless production mode', () => { beforeAll(async () => { await fs.writeFile( nextConfig, diff --git a/test/integration/ssg-dynamic-routes-404-page/test/index.test.js b/test/integration/ssg-dynamic-routes-404-page/test/index.test.js index 30057f4bd0c81..fa1ebd1730606 100644 --- a/test/integration/ssg-dynamic-routes-404-page/test/index.test.js +++ b/test/integration/ssg-dynamic-routes-404-page/test/index.test.js @@ -45,7 +45,7 @@ describe('Custom 404 Page for static site generation with dynamic routes', () => runTests('server') }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { afterAll(async () => { await fs.remove(nextConfig) await killApp(app) diff --git a/test/integration/static-page-name/test/index.test.js b/test/integration/static-page-name/test/index.test.js index 60015a9ca5328..5a0fce53d87af 100644 --- a/test/integration/static-page-name/test/index.test.js +++ b/test/integration/static-page-name/test/index.test.js @@ -52,7 +52,7 @@ describe('Static Page Name', () => { runTests() }) - describe('serverless mode', () => { + describe.skip('serverless mode', () => { beforeAll(async () => { appPort = await findPort() await fs.writeFile( diff --git a/test/production/middleware-is-not-allowed-when-using-serverless-target/index.test.ts b/test/production/middleware-is-not-allowed-when-using-serverless-target/index.test.ts index 555ac5c8c76e5..e3eafa950a23f 100644 --- a/test/production/middleware-is-not-allowed-when-using-serverless-target/index.test.ts +++ b/test/production/middleware-is-not-allowed-when-using-serverless-target/index.test.ts @@ -1,7 +1,7 @@ import { nextBuild } from 'next-test-utils' import path from 'path' -describe('Middleware is not allowed when using serverless target', () => { +describe.skip('Middleware is not allowed when using serverless target', () => { it('fails to build', async () => { const { code, stderr } = await nextBuild( path.resolve(__dirname, './app'),