From 08dd3404e6edb93e8a7917419aa5021c465c43ab Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 13 Jul 2023 17:42:19 +0200 Subject: [PATCH 01/11] Catch layout error in global-error --- .../next/src/server/app-render/app-render.tsx | 6 +++- .../app/error.tsx | 10 +++--- .../app/layout.tsx | 2 ++ .../app-dir/global-error/layout-error.test.ts | 32 +++++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 test/e2e/app-dir/global-error/layout-error.test.ts diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 4bd3cf103e025..69b95d933aa84 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1628,7 +1628,11 @@ export async function renderToHTMLOrFlight( ) const use404Error = res.statusCode === 404 - const useDefaultError = res.statusCode < 400 || res.statusCode === 307 + // When it's in error state but status code is not 200, we should render global-error + const useGlobalError = + res.statusCode === 200 && process.env.NODE_ENV === 'production' + const useDefaultError = + (res.statusCode < 400 || res.statusCode === 307) && !useGlobalError const { layout } = loaderTree[2] const injectedCSS = new Set() diff --git a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx index 2d203c0ac82cd..2c07aa5dc7303 100644 --- a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx +++ b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx @@ -4,10 +4,12 @@ import Link from 'next/link' export default function ErrorComponent() { return ( <> -

Error Happened!

- - To Result - +
+

Error Happened!

+ + To Result + +
) } diff --git a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx index e7077399c03ce..69e2ad5092a0e 100644 --- a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx +++ b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx @@ -1,3 +1,5 @@ +export const revalidate = 0 + export default function Root({ children }: { children: React.ReactNode }) { return ( diff --git a/test/e2e/app-dir/global-error/layout-error.test.ts b/test/e2e/app-dir/global-error/layout-error.test.ts new file mode 100644 index 0000000000000..db83aa336ae1b --- /dev/null +++ b/test/e2e/app-dir/global-error/layout-error.test.ts @@ -0,0 +1,32 @@ +import { getRedboxHeader, hasRedbox } from 'next-test-utils' +import { createNextDescribe } from 'e2e-utils' + +async function testDev(browser, errorRegex) { + expect(await hasRedbox(browser, true)).toBe(true) + expect(await getRedboxHeader(browser)).toMatch(errorRegex) +} + +createNextDescribe( + 'app dir - global error - layout error', + { + files: { + 'app/layout.js': `throw new Error('Global error: layout error')`, + 'app/page.js': `export default function page() { return
Page
}`, + }, + }, + ({ next, isNextDev }) => { + it('should render global error for error in server components', async () => { + const browser = await next.browser('/') + + if (isNextDev) { + await testDev(browser, /Global error: layout error/) + } else { + expect(await browser.elementByCss('h1').text()).toBe('Global Error') + expect(await browser.elementByCss('#error').text()).toBe( + 'Global error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' + ) + expect(await browser.elementByCss('#digest').text()).toMatch(/\w+/) + } + }) + } +) From 4b4433de509598c1ae7ebe60e27bd76d82e1158e Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 13 Jul 2023 18:02:09 +0200 Subject: [PATCH 02/11] organize test --- .../global-error/{ => basic}/app/client/page.js | 0 .../global-error/{ => basic}/app/global-error.js | 0 .../app-dir/global-error/{ => basic}/app/layout.js | 0 .../{ => basic}/app/ssr/client/page.js | 0 .../{ => basic}/app/ssr/server/page.js | 0 .../app-dir/global-error/{ => basic}/index.test.ts | 0 .../global-error/layout-error/app/global-error.js | 14 ++++++++++++++ .../global-error/layout-error/app/layout.js | 5 +++++ .../app-dir/global-error/layout-error/app/page.js | 3 +++ .../index.test.ts} | 6 ++---- 10 files changed, 24 insertions(+), 4 deletions(-) rename test/e2e/app-dir/global-error/{ => basic}/app/client/page.js (100%) rename test/e2e/app-dir/global-error/{ => basic}/app/global-error.js (100%) rename test/e2e/app-dir/global-error/{ => basic}/app/layout.js (100%) rename test/e2e/app-dir/global-error/{ => basic}/app/ssr/client/page.js (100%) rename test/e2e/app-dir/global-error/{ => basic}/app/ssr/server/page.js (100%) rename test/e2e/app-dir/global-error/{ => basic}/index.test.ts (100%) create mode 100644 test/e2e/app-dir/global-error/layout-error/app/global-error.js create mode 100644 test/e2e/app-dir/global-error/layout-error/app/layout.js create mode 100644 test/e2e/app-dir/global-error/layout-error/app/page.js rename test/e2e/app-dir/global-error/{layout-error.test.ts => layout-error/index.test.ts} (86%) diff --git a/test/e2e/app-dir/global-error/app/client/page.js b/test/e2e/app-dir/global-error/basic/app/client/page.js similarity index 100% rename from test/e2e/app-dir/global-error/app/client/page.js rename to test/e2e/app-dir/global-error/basic/app/client/page.js diff --git a/test/e2e/app-dir/global-error/app/global-error.js b/test/e2e/app-dir/global-error/basic/app/global-error.js similarity index 100% rename from test/e2e/app-dir/global-error/app/global-error.js rename to test/e2e/app-dir/global-error/basic/app/global-error.js diff --git a/test/e2e/app-dir/global-error/app/layout.js b/test/e2e/app-dir/global-error/basic/app/layout.js similarity index 100% rename from test/e2e/app-dir/global-error/app/layout.js rename to test/e2e/app-dir/global-error/basic/app/layout.js diff --git a/test/e2e/app-dir/global-error/app/ssr/client/page.js b/test/e2e/app-dir/global-error/basic/app/ssr/client/page.js similarity index 100% rename from test/e2e/app-dir/global-error/app/ssr/client/page.js rename to test/e2e/app-dir/global-error/basic/app/ssr/client/page.js diff --git a/test/e2e/app-dir/global-error/app/ssr/server/page.js b/test/e2e/app-dir/global-error/basic/app/ssr/server/page.js similarity index 100% rename from test/e2e/app-dir/global-error/app/ssr/server/page.js rename to test/e2e/app-dir/global-error/basic/app/ssr/server/page.js diff --git a/test/e2e/app-dir/global-error/index.test.ts b/test/e2e/app-dir/global-error/basic/index.test.ts similarity index 100% rename from test/e2e/app-dir/global-error/index.test.ts rename to test/e2e/app-dir/global-error/basic/index.test.ts diff --git a/test/e2e/app-dir/global-error/layout-error/app/global-error.js b/test/e2e/app-dir/global-error/layout-error/app/global-error.js new file mode 100644 index 0000000000000..d960556d75cd5 --- /dev/null +++ b/test/e2e/app-dir/global-error/layout-error/app/global-error.js @@ -0,0 +1,14 @@ +'use client' + +export default function GlobalError({ error }) { + return ( + + + +

Global Error

+

{`Global error: ${error?.message}`}

+ {error?.digest &&

{error?.digest}

} + + + ) +} diff --git a/test/e2e/app-dir/global-error/layout-error/app/layout.js b/test/e2e/app-dir/global-error/layout-error/app/layout.js new file mode 100644 index 0000000000000..6fc4fecd68e10 --- /dev/null +++ b/test/e2e/app-dir/global-error/layout-error/app/layout.js @@ -0,0 +1,5 @@ +export default function layout() { + throw new Error('Global error: layout error') +} + +export const revalidate = 0 diff --git a/test/e2e/app-dir/global-error/layout-error/app/page.js b/test/e2e/app-dir/global-error/layout-error/app/page.js new file mode 100644 index 0000000000000..a5192c0ea9cfa --- /dev/null +++ b/test/e2e/app-dir/global-error/layout-error/app/page.js @@ -0,0 +1,3 @@ +export default function page() { + return
Page
+} diff --git a/test/e2e/app-dir/global-error/layout-error.test.ts b/test/e2e/app-dir/global-error/layout-error/index.test.ts similarity index 86% rename from test/e2e/app-dir/global-error/layout-error.test.ts rename to test/e2e/app-dir/global-error/layout-error/index.test.ts index db83aa336ae1b..707094fdc3176 100644 --- a/test/e2e/app-dir/global-error/layout-error.test.ts +++ b/test/e2e/app-dir/global-error/layout-error/index.test.ts @@ -9,10 +9,8 @@ async function testDev(browser, errorRegex) { createNextDescribe( 'app dir - global error - layout error', { - files: { - 'app/layout.js': `throw new Error('Global error: layout error')`, - 'app/page.js': `export default function page() { return
Page
}`, - }, + files: __dirname, + skipDeployment: true, }, ({ next, isNextDev }) => { it('should render global error for error in server components', async () => { From 90f6d077d180f8f3c1b744280c8dac42d109b59b Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 13 Jul 2023 18:24:11 +0200 Subject: [PATCH 03/11] revert --- .../error-boundary-and-not-found-linking/app/error.tsx | 10 ++++------ .../app/layout.tsx | 2 -- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx index 2c07aa5dc7303..2d203c0ac82cd 100644 --- a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx +++ b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/error.tsx @@ -4,12 +4,10 @@ import Link from 'next/link' export default function ErrorComponent() { return ( <> -
-

Error Happened!

- - To Result - -
+

Error Happened!

+ + To Result + ) } diff --git a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx index 69e2ad5092a0e..e7077399c03ce 100644 --- a/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx +++ b/test/e2e/app-dir/error-boundary-and-not-found-linking/app/layout.tsx @@ -1,5 +1,3 @@ -export const revalidate = 0 - export default function Root({ children }: { children: React.ReactNode }) { return ( From d20e4b1bbba7c214f5a0b0a5362fe2482eb96343 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 13 Jul 2023 18:41:16 +0200 Subject: [PATCH 04/11] skip internal error --- packages/next/src/server/app-render/app-render.tsx | 10 ++++++++-- .../next/src/shared/lib/lazy-dynamic/no-ssr-error.ts | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 69b95d933aa84..17bdaf5bc873e 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -72,7 +72,10 @@ import { createFlightRouterStateFromLoaderTree, } from './create-flight-router-state-from-loader-tree' import { handleAction } from './action-handler' -import { NEXT_DYNAMIC_NO_SSR_CODE } from '../../shared/lib/lazy-dynamic/no-ssr-error' +import { + NEXT_DYNAMIC_NO_SSR_CODE, + isNextDynamicNoSSRError, +} from '../../shared/lib/lazy-dynamic/no-ssr-error' import { warn } from '../../build/output/log' import { appendMutableCookies } from '../web/spec-extension/adapters/request-cookies' import { ComponentsType } from '../../build/webpack/loaders/next-app-loader' @@ -1630,7 +1633,10 @@ export async function renderToHTMLOrFlight( const use404Error = res.statusCode === 404 // When it's in error state but status code is not 200, we should render global-error const useGlobalError = - res.statusCode === 200 && process.env.NODE_ENV === 'production' + res.statusCode === 200 && + // skip the built-in error + !isNextDynamicNoSSRError(err) && + process.env.NODE_ENV === 'production' const useDefaultError = (res.statusCode < 400 || res.statusCode === 307) && !useGlobalError diff --git a/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts b/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts index 74303dc74bd45..53bcac64fa507 100644 --- a/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts +++ b/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts @@ -1,3 +1,5 @@ // This has to be a shared module which is shared between client component error boundary and dynamic component export const NEXT_DYNAMIC_NO_SSR_CODE = 'NEXT_DYNAMIC_NO_SSR_CODE' +export const isNextDynamicNoSSRError = (err: any) => + err && err.digest === NEXT_DYNAMIC_NO_SSR_CODE From f2a3b58cf1bcc45eb7595984d70ca9f21e6ebe94 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 13 Jul 2023 23:24:42 +0200 Subject: [PATCH 05/11] fix app-render --- .../next/src/server/app-render/app-render.tsx | 88 ++++++++----------- .../shared/lib/lazy-dynamic/no-ssr-error.ts | 2 - 2 files changed, 38 insertions(+), 52 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 17bdaf5bc873e..2ff7a093e70d3 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -72,10 +72,7 @@ import { createFlightRouterStateFromLoaderTree, } from './create-flight-router-state-from-loader-tree' import { handleAction } from './action-handler' -import { - NEXT_DYNAMIC_NO_SSR_CODE, - isNextDynamicNoSSRError, -} from '../../shared/lib/lazy-dynamic/no-ssr-error' +import { NEXT_DYNAMIC_NO_SSR_CODE } from '../../shared/lib/lazy-dynamic/no-ssr-error' import { warn } from '../../build/output/log' import { appendMutableCookies } from '../web/spec-extension/adapters/request-cookies' import { ComponentsType } from '../../build/webpack/loaders/next-app-loader' @@ -1270,7 +1267,7 @@ export async function renderToHTMLOrFlight( let serverErrorComponentsInlinedTransformStream: TransformStream< Uint8Array, Uint8Array - > = new TransformStream() + > = serverComponentsInlinedTransformStream // new TransformStream() // Get the nonce from the incoming request if it has one. const csp = req.headers['content-security-policy'] @@ -1631,14 +1628,8 @@ export async function renderToHTMLOrFlight( ) const use404Error = res.statusCode === 404 + const useDefaultError = res.statusCode < 400 || res.statusCode === 307 // When it's in error state but status code is not 200, we should render global-error - const useGlobalError = - res.statusCode === 200 && - // skip the built-in error - !isNextDynamicNoSSRError(err) && - process.env.NODE_ENV === 'production' - const useDefaultError = - (res.statusCode < 400 || res.statusCode === 307) && !useGlobalError const { layout } = loaderTree[2] const injectedCSS = new Set() @@ -1653,48 +1644,45 @@ export async function renderToHTMLOrFlight( ? interopDefault(await rootLayoutModule()) : null - const serverErrorElement = useDefaultError - ? defaultErrorComponent - : React.createElement( - createServerComponentRenderer( - async () => { - // only pass plain object to client - return ( - <> - {/* @ts-expect-error allow to use async server component */} - - {use404Error ? ( - <> + const serverErrorElement = useDefaultError ? ( + defaultErrorComponent + ) : ( + + + {/* @ts-expect-error allow to use async server component */} + + + + {React.createElement( + createServerComponentRenderer( + async () => { + // only pass plain object to client + return ( + <> + {use404Error ? ( {notFoundStyles} - - ) : ( - - )} - - ) - }, - ComponentMod, - serverErrorComponentsRenderOpts, - serverComponentsErrorHandler, - nonce - ) - ) + ) : undefined} + + ) + }, + ComponentMod, + serverErrorComponentsRenderOpts, + serverComponentsErrorHandler, + nonce + ) + )} + + + ) const renderStream = await renderToInitialStream({ ReactDOMServer: require('react-dom/server.edge'), diff --git a/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts b/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts index 53bcac64fa507..74303dc74bd45 100644 --- a/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts +++ b/packages/next/src/shared/lib/lazy-dynamic/no-ssr-error.ts @@ -1,5 +1,3 @@ // This has to be a shared module which is shared between client component error boundary and dynamic component export const NEXT_DYNAMIC_NO_SSR_CODE = 'NEXT_DYNAMIC_NO_SSR_CODE' -export const isNextDynamicNoSSRError = (err: any) => - err && err.digest === NEXT_DYNAMIC_NO_SSR_CODE From 766db1bfc625e4e2a8b84311bebebe64fb82c0cf Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 13 Jul 2023 23:41:36 +0200 Subject: [PATCH 06/11] merge --- packages/next/src/lib/metadata/metadata.tsx | 4 + .../next/src/server/app-render/app-render.tsx | 127 ++++++++---------- 2 files changed, 58 insertions(+), 73 deletions(-) diff --git a/packages/next/src/lib/metadata/metadata.tsx b/packages/next/src/lib/metadata/metadata.tsx index 3ac86f0f74db8..ec5c5f0935162 100644 --- a/packages/next/src/lib/metadata/metadata.tsx +++ b/packages/next/src/lib/metadata/metadata.tsx @@ -25,11 +25,13 @@ export async function MetadataTree({ pathname, searchParams, getDynamicParamFromSegment, + appUsingSizeAdjust, }: { tree: LoaderTree pathname: string searchParams: { [key: string]: any } getDynamicParamFromSegment: GetDynamicParamFromSegment + appUsingSizeAdjust: boolean }) { const metadataContext = { pathname, @@ -56,6 +58,8 @@ export async function MetadataTree({ IconsMetadata({ icons: metadata.icons }), ]) + if (appUsingSizeAdjust) elements.push() + return ( <> {elements.map((el, index) => { diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 2ff7a093e70d3..e7925877a8c2b 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -82,6 +82,19 @@ export const isEdgeRuntime = process.env.NEXT_RUNTIME === 'edge' const emptyLoaderTree: LoaderTree = ['', {}, {}] +const ErrorHtml = ({ + head, + children, +}: { + head?: React.ReactNode + children?: React.ReactNode +}) => ( + + {head} + {children} + +) + export type GetDynamicParamFromSegment = ( // [slug] / [[slug]] / [...slug] segment: string @@ -195,7 +208,7 @@ export async function renderToHTMLOrFlight( serverActionsBodySizeLimit, } = renderOpts - const appUsingSizeAdjust = nextFontManifest?.appUsingSizeAdjust + const appUsingSizeAdjust = !!nextFontManifest?.appUsingSizeAdjust const clientReferenceManifest = renderOpts.clientReferenceManifest! @@ -1216,8 +1229,8 @@ export async function renderToHTMLOrFlight( pathname={pathname} searchParams={providedSearchParams} getDynamicParamFromSegment={getDynamicParamFromSegment} + appUsingSizeAdjust={appUsingSizeAdjust} /> - {appUsingSizeAdjust ? : null} ), injectedCSS: new Set(), @@ -1264,11 +1277,6 @@ export async function renderToHTMLOrFlight( Uint8Array > = new TransformStream() - let serverErrorComponentsInlinedTransformStream: TransformStream< - Uint8Array, - Uint8Array - > = serverComponentsInlinedTransformStream // new TransformStream() - // Get the nonce from the incoming request if it has one. const csp = req.headers['content-security-policy'] let nonce: string | undefined @@ -1284,7 +1292,7 @@ export async function renderToHTMLOrFlight( } const serverErrorComponentsRenderOpts = { - transformStream: serverErrorComponentsInlinedTransformStream, + transformStream: serverComponentsInlinedTransformStream, clientReferenceManifest, serverContexts, rscChunks: [], @@ -1367,6 +1375,7 @@ export async function renderToHTMLOrFlight( pathname={pathname} searchParams={providedSearchParams} getDynamicParamFromSegment={getDynamicParamFromSegment} + appUsingSizeAdjust={appUsingSizeAdjust} /> ) @@ -1384,22 +1393,15 @@ export async function renderToHTMLOrFlight( assetPrefix={assetPrefix} initialCanonicalUrl={pathname} initialTree={initialTree} - initialHead={ - <> - {createMetadata(loaderTree)} - {appUsingSizeAdjust ? : null} - - } + initialHead={<>{createMetadata(loaderTree)}} globalErrorComponent={GlobalError} notFound={ NotFound ? ( - - - {createMetadata(loaderTree)} - {notFoundStyles} - - - + + {createMetadata(loaderTree)} + {notFoundStyles} + + ) : undefined } asNotFound={props.asNotFound} @@ -1610,23 +1612,6 @@ export async function renderToHTMLOrFlight( res.setHeader('Location', getURLFromRedirectError(err)) } - const defaultErrorComponent = ( - - - {/* @ts-expect-error allow to use async server component */} - - {appUsingSizeAdjust ? : null} - - - - ) - const use404Error = res.statusCode === 404 const useDefaultError = res.statusCode < 400 || res.statusCode === 307 // When it's in error state but status code is not 200, we should render global-error @@ -1644,44 +1629,43 @@ export async function renderToHTMLOrFlight( ? interopDefault(await rootLayoutModule()) : null - const serverErrorElement = useDefaultError ? ( - defaultErrorComponent - ) : ( - - - {/* @ts-expect-error allow to use async server component */} + const serverErrorElement = ( + - - - {React.createElement( - createServerComponentRenderer( - async () => { - // only pass plain object to client - return ( - <> - {use404Error ? ( - - {notFoundStyles} - - - ) : undefined} - - ) - }, - ComponentMod, - serverErrorComponentsRenderOpts, - serverComponentsErrorHandler, - nonce - ) - )} - - + } + > + {useDefaultError + ? null + : React.createElement( + createServerComponentRenderer( + async () => { + return ( + <> + {use404Error ? ( + + {notFoundStyles} + + + ) : undefined} + + ) + }, + ComponentMod, + serverErrorComponentsRenderOpts, + serverComponentsErrorHandler, + nonce + ) + )} + ) const renderStream = await renderToInitialStream({ @@ -1706,10 +1690,7 @@ export async function renderToHTMLOrFlight( }) return await continueFromInitialStream(renderStream, { - dataStream: (useDefaultError - ? serverComponentsInlinedTransformStream - : serverErrorComponentsInlinedTransformStream - ).readable, + dataStream: serverComponentsInlinedTransformStream.readable, generateStaticHTML: staticGenerationStore.isStaticGeneration, getServerInsertedHTML, serverInsertedHTMLToHead: true, From cd72bfc87af93f5097b16196aac90dcefd85e6cc Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 13 Jul 2023 23:53:59 +0200 Subject: [PATCH 07/11] fix streaming --- packages/next/src/server/app-render/app-render.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index e7925877a8c2b..5d4dbdf8582c3 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1272,7 +1272,12 @@ export async function renderToHTMLOrFlight( /** GlobalError can be either the default error boundary or the overwritten app/global-error.js **/ ComponentMod.GlobalError as typeof import('../../client/components/error-boundary').GlobalError - let serverComponentsInlinedTransformStream: TransformStream< + const serverComponentsInlinedTransformStream: TransformStream< + Uint8Array, + Uint8Array + > = new TransformStream() + + const serverErrorComponentsInlinedTransformStream: TransformStream< Uint8Array, Uint8Array > = new TransformStream() @@ -1292,7 +1297,7 @@ export async function renderToHTMLOrFlight( } const serverErrorComponentsRenderOpts = { - transformStream: serverComponentsInlinedTransformStream, + transformStream: serverErrorComponentsInlinedTransformStream, clientReferenceManifest, serverContexts, rscChunks: [], @@ -1690,7 +1695,10 @@ export async function renderToHTMLOrFlight( }) return await continueFromInitialStream(renderStream, { - dataStream: serverComponentsInlinedTransformStream.readable, + dataStream: (useDefaultError + ? serverComponentsInlinedTransformStream + : serverErrorComponentsInlinedTransformStream + ).readable, generateStaticHTML: staticGenerationStore.isStaticGeneration, getServerInsertedHTML, serverInsertedHTMLToHead: true, From 3a8219bc7c6a36da6c8caa60674ab6fbe2535f8d Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 14 Jul 2023 00:35:07 +0200 Subject: [PATCH 08/11] fix no index --- .../next/src/server/app-render/app-render.tsx | 20 +++++-------------- .../create-server-components-renderer.tsx | 15 ++++++++++++++ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 5d4dbdf8582c3..0e1c1d625c9d9 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -17,7 +17,10 @@ import type { RequestAsyncStorage } from '../../client/components/request-async- import React from 'react' import { NotFound as DefaultNotFound } from '../../client/components/error' -import { createServerComponentRenderer } from './create-server-components-renderer' +import { + createServerComponentRenderer, + ErrorHtml, +} from './create-server-components-renderer' import { ParsedUrlQuery } from 'querystring' import { NextParsedUrlQuery } from '../request-meta' @@ -82,19 +85,6 @@ export const isEdgeRuntime = process.env.NEXT_RUNTIME === 'edge' const emptyLoaderTree: LoaderTree = ['', {}, {}] -const ErrorHtml = ({ - head, - children, -}: { - head?: React.ReactNode - children?: React.ReactNode -}) => ( - - {head} - {children} - -) - export type GetDynamicParamFromSegment = ( // [slug] / [[slug]] / [...slug] segment: string @@ -1619,7 +1609,6 @@ export async function renderToHTMLOrFlight( const use404Error = res.statusCode === 404 const useDefaultError = res.statusCode < 400 || res.statusCode === 307 - // When it's in error state but status code is not 200, we should render global-error const { layout } = loaderTree[2] const injectedCSS = new Set() @@ -1658,6 +1647,7 @@ export async function renderToHTMLOrFlight( {use404Error ? ( {notFoundStyles} + ) : undefined} diff --git a/packages/next/src/server/app-render/create-server-components-renderer.tsx b/packages/next/src/server/app-render/create-server-components-renderer.tsx index 0d11231ed110d..5fdc1008bf819 100644 --- a/packages/next/src/server/app-render/create-server-components-renderer.tsx +++ b/packages/next/src/server/app-render/create-server-components-renderer.tsx @@ -75,3 +75,18 @@ export function createServerComponentRenderer( return use(response) } } + +export function ErrorHtml({ + head, + children, +}: { + head?: React.ReactNode + children?: React.ReactNode +}) { + return ( + + {head} + {children} + + ) +} From 118ed4d094fababad0e3a07df026f3f9def3b9a1 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 14 Jul 2023 01:03:47 +0200 Subject: [PATCH 09/11] fix duplicated no index --- packages/next/src/server/app-render/app-render.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 0e1c1d625c9d9..7eab68bba7d52 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1487,11 +1487,7 @@ export async function renderToHTMLOrFlight( flushedErrorMetaTagsUntilIndex++ ) { const error = allCapturedErrors[flushedErrorMetaTagsUntilIndex] - if (isNotFoundError(error)) { - errorMetaTags.push( - - ) - } else if (isRedirectError(error)) { + if (isRedirectError(error)) { const redirectUrl = getURLFromRedirectError(error) if (redirectUrl) { errorMetaTags.push( From 8714116b8ac2a53054a54fd74a5bbd0ccdff2268 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 14 Jul 2023 01:42:48 +0200 Subject: [PATCH 10/11] fix missing noindex --- .../next/src/server/app-render/app-render.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 7eab68bba7d52..a18bc42708991 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1477,17 +1477,21 @@ export async function renderToHTMLOrFlight( let polyfillsFlushed = false let flushedErrorMetaTagsUntilIndex = 0 - const getServerInsertedHTML = () => { + const getServerInsertedHTML = (capturedErrors: Error[]) => { // Loop through all the errors that have been captured but not yet // flushed. const errorMetaTags = [] for ( ; - flushedErrorMetaTagsUntilIndex < allCapturedErrors.length; + flushedErrorMetaTagsUntilIndex < capturedErrors.length; flushedErrorMetaTagsUntilIndex++ ) { - const error = allCapturedErrors[flushedErrorMetaTagsUntilIndex] - if (isRedirectError(error)) { + const error = capturedErrors[flushedErrorMetaTagsUntilIndex] + if (isNotFoundError(error)) { + errorMetaTags.push( + + ) + } else if (isRedirectError(error)) { const redirectUrl = getURLFromRedirectError(error) if (redirectUrl) { errorMetaTags.push( @@ -1564,7 +1568,8 @@ export async function renderToHTMLOrFlight( dataStream: serverComponentsInlinedTransformStream.readable, generateStaticHTML: staticGenerationStore.isStaticGeneration || generateStaticHTML, - getServerInsertedHTML, + getServerInsertedHTML: () => + getServerInsertedHTML(allCapturedErrors), serverInsertedHTMLToHead: true, ...validateRootLayout, }) @@ -1686,7 +1691,7 @@ export async function renderToHTMLOrFlight( : serverErrorComponentsInlinedTransformStream ).readable, generateStaticHTML: staticGenerationStore.isStaticGeneration, - getServerInsertedHTML, + getServerInsertedHTML: () => getServerInsertedHTML([]), serverInsertedHTMLToHead: true, ...validateRootLayout, }) From 2947d63c183619ae9a472e672bc476f8590f9aef Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 14 Jul 2023 02:03:00 +0200 Subject: [PATCH 11/11] fix lint --- packages/next/src/server/app-render/app-render.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index a18bc42708991..752eca8ec9e68 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1477,16 +1477,16 @@ export async function renderToHTMLOrFlight( let polyfillsFlushed = false let flushedErrorMetaTagsUntilIndex = 0 - const getServerInsertedHTML = (capturedErrors: Error[]) => { + const getServerInsertedHTML = (serverCapturedErrors: Error[]) => { // Loop through all the errors that have been captured but not yet // flushed. const errorMetaTags = [] for ( ; - flushedErrorMetaTagsUntilIndex < capturedErrors.length; + flushedErrorMetaTagsUntilIndex < serverCapturedErrors.length; flushedErrorMetaTagsUntilIndex++ ) { - const error = capturedErrors[flushedErrorMetaTagsUntilIndex] + const error = serverCapturedErrors[flushedErrorMetaTagsUntilIndex] if (isNotFoundError(error)) { errorMetaTags.push(