From 8a2bb49d6da6e59156c255ca8503dad103029ba5 Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 14 Jul 2022 12:26:25 +0200 Subject: [PATCH] Fix failed to hydrate error with global CSS (#38626) Temporarily we need to ensure that `` tags are injected to `` in the stream. ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have 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 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.md#adding-examples) --- .../components/layout-router.client.tsx | 6 ++-- packages/next/server/app-render.tsx | 1 + .../next/server/node-web-streams-helper.ts | 30 +++++++++++-------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/next/client/components/layout-router.client.tsx b/packages/next/client/components/layout-router.client.tsx index a7bcf85f3357..fd3b8168ee23 100644 --- a/packages/next/client/components/layout-router.client.tsx +++ b/packages/next/client/components/layout-router.client.tsx @@ -235,7 +235,7 @@ export default function OuterLayoutRouter({ childProp: ChildProp loading: React.ReactNode | undefined }) { - const { childNodes, tree, url, stylesheets } = useContext(AppTreeContext) + const { childNodes, tree, url } = useContext(AppTreeContext) let childNodesForParallelRouter = childNodes.get(parallelRouterKey) if (!childNodesForParallelRouter) { @@ -256,11 +256,11 @@ export default function OuterLayoutRouter({ return ( <> - {stylesheets + {/* {stylesheets ? stylesheets.map((href) => ( )) - : null} + : null} */} {preservedSegments.map((preservedSegment) => { return ( diff --git a/packages/next/server/app-render.tsx b/packages/next/server/app-render.tsx index 95bfd1e10670..a27550af9f4f 100644 --- a/packages/next/server/app-render.tsx +++ b/packages/next/server/app-render.tsx @@ -946,6 +946,7 @@ export async function renderToHTML( dataStream: serverComponentsInlinedTransformStream?.readable, generateStaticHTML: generateStaticHTML || !hasConcurrentFeatures, flushEffectHandler, + initialStylesheets, }) } diff --git a/packages/next/server/node-web-streams-helper.ts b/packages/next/server/node-web-streams-helper.ts index 769df24adefd..2e4f8b19474c 100644 --- a/packages/next/server/node-web-streams-helper.ts +++ b/packages/next/server/node-web-streams-helper.ts @@ -136,25 +136,18 @@ export function createFlushEffectStream( }) } -export function createDevScriptTransformStream(): TransformStream< - Uint8Array, - Uint8Array -> { +export function createHeadInjectionTransformStream( + inject: string +): TransformStream { let injected = false - const foucTags = ` - ` return new TransformStream({ transform(chunk, controller) { const content = decodeText(chunk) let index if (!injected && (index = content.indexOf(' generateStaticHTML: boolean flushEffectHandler?: () => string + initialStylesheets?: string[] } ): Promise> { const closeTag = '' @@ -204,7 +199,18 @@ export async function continueFromInitialStream( suffixUnclosed != null ? createDeferredSuffixStream(suffixUnclosed) : null, dataStream ? createInlineDataStream(dataStream) : null, suffixUnclosed != null ? createSuffixStream(closeTag) : null, - dev ? createDevScriptTransformStream() : null, + createHeadInjectionTransformStream( + dev + ? ` + ` + : initialStylesheets + ? initialStylesheets + .map((href) => ``) + .join('') + : '' + ), ].filter(nonNullable) return transforms.reduce(