Upstream change
Next.js fixed a race condition in Pages Router SSR where dynamic styled-jsx styles were silently dropped from rendered HTML.
Commit: 9853944 — "Fix styled-jsx race condition: styles lost due to concurrent rendering (#92459)"
What changed
In packages/next/src/server/render.tsx, styledJsxInsertedHTML() was previously called concurrently with the page render via Promise.all:
const [rawStyledJsxInsertedHTML, content] = await Promise.all([
renderToString(styledJsxInsertedHTML()),
(async () => { /* render the page */ })(),
])
Because both ran at the same time, styledJsxInsertedHTML() could flush the styled-jsx registry before the page render had finished populating it. Dynamic styled-jsx styles (those with interpolated expressions that compute class names at runtime via DJB2 hashing) were silently dropped from SSR output, causing a flash of unstyled content.
Fix: Serialize the operations — render the page first, then call styledJsxInsertedHTML().
Relevance to vinext
vinext reimplements Pages Router SSR in server/dev-server.ts and server/prod-server.ts. If vinext's SSR render path for Pages Router apps also reads the styled-jsx registry concurrently with (or before) page rendering completes, the same race condition could cause dynamic styled-jsx styles to be missing from SSR output.
Action items:
- Check whether vinext's Pages Router SSR path calls
styledJsxInsertedHTML() or reads the styled-jsx registry
- If it does, verify the registry is read after page rendering completes (not concurrently)
- If the pattern exists, fix it and add a test with dynamic styled-jsx (interpolated expressions) to verify styles are present in SSR output
Upstream change
Next.js fixed a race condition in Pages Router SSR where dynamic styled-jsx styles were silently dropped from rendered HTML.
Commit:
9853944— "Fix styled-jsx race condition: styles lost due to concurrent rendering (#92459)"What changed
In
packages/next/src/server/render.tsx,styledJsxInsertedHTML()was previously called concurrently with the page render viaPromise.all:Because both ran at the same time,
styledJsxInsertedHTML()could flush the styled-jsx registry before the page render had finished populating it. Dynamic styled-jsx styles (those with interpolated expressions that compute class names at runtime via DJB2 hashing) were silently dropped from SSR output, causing a flash of unstyled content.Fix: Serialize the operations — render the page first, then call
styledJsxInsertedHTML().Relevance to vinext
vinext reimplements Pages Router SSR in
server/dev-server.tsandserver/prod-server.ts. If vinext's SSR render path for Pages Router apps also reads the styled-jsx registry concurrently with (or before) page rendering completes, the same race condition could cause dynamic styled-jsx styles to be missing from SSR output.Action items:
styledJsxInsertedHTML()or reads the styled-jsx registry