Link to the code that reproduces this issue
https://github.com/mikaelh/next-inlinecss-rsc-dup-repro
To Reproduce
npm install (pulls next@canary) then npm run build on the linked repo. It is a minimal App Router app: output: "standalone", experimental.inlineCss: true, a 155 KB global stylesheet imported in the root layout, and one [slug] route with generateStaticParams → 60 tiny static pages.
- Inspect
.next/standalone/.next/server/app, e.g. grep -rl '\.u1000{' .next/standalone/.next/server/app | wc -l and count occurrences per file.
Current vs. Expected behavior
Current (verified on next@16.3.0-canary.66): with inlineCss, the whole stylesheet is inlined into each page's HTML <style> and also serialized into the page's RSC payloads — the inline flight inside the .html, the page.rsc, and each .segments/*.segment.rsc.
Observed in the repro for one trivial static page (a1.html, 411 KB for "tiny content"): 1 <style> block, but the CSS marker rule appears 3× (<style> + flight). Across the build the 155 KB CSS is embedded in 62 .html, 186 .rsc (of which 124 are *.segments/*.segment.rsc) → .next/server/app = 69 MB for 60 pages of "tiny content". So each prerendered page stores the stylesheet ~3–4× (HTML <style> + HTML flight + page.rsc + each segment.rsc); build output scales with CSS_size × pages × ~4.
Amplifier: moving the @import from the root layout into a nested layout (route group) makes the per-segment copies multiply (~2× → ~5× per page in a larger app), so per-route CSS scoping is counter-productive under inlineCss. On a real content site (~700 prerendered pages, 172 KB CSS) the duplicated CSS is ~205 MB of a 453 MB server/app; moving CSS to a nested layout took server/app from 453 MB to 868 MB.
Expected: inlined CSS referenced/deduplicated once per prerendered page rather than copied into every RSC/segment payload. The segment-cache / client-navigation RSC payloads don't need the full stylesheet embedded — on client navigation the browser already has the styles applied. Keep inlining into the initial HTML (the FCP/LCP win) without duplicating across the RSC.
Provide environment information
Operating System: Linux
Binaries:
Node: 24.x
Relevant Packages:
next: 16.3.0-canary.66
react: 19.2.0
react-dom: 19.2.0
Next.js Config:
output: "standalone"
experimental.inlineCss: true
Which area(s) are affected? (Select all that apply)
Output (Standalone), Partial Prerendering (PPR)
Which stage(s) are affected? (Select all that apply)
next build (local)
Additional context
inlineCss is otherwise a real FCP/LCP win, so disabling it is an unwanted trade-off — the request is to keep the initial-HTML inline but stop duplicating the bundle across the RSC/segment payloads. Measured via du + counting the inlined CSS chunk across .html / .rsc / .segments/*.segment.rsc. (Supersedes #95140, which was auto-closed for a parsing issue — the reproduction link is now in the correct field.)
Link to the code that reproduces this issue
https://github.com/mikaelh/next-inlinecss-rsc-dup-repro
To Reproduce
npm install(pullsnext@canary) thennpm run buildon the linked repo. It is a minimal App Router app:output: "standalone",experimental.inlineCss: true, a 155 KB global stylesheet imported in the root layout, and one[slug]route withgenerateStaticParams→ 60 tiny static pages..next/standalone/.next/server/app, e.g.grep -rl '\.u1000{' .next/standalone/.next/server/app | wc -land count occurrences per file.Current vs. Expected behavior
Current (verified on
next@16.3.0-canary.66): withinlineCss, the whole stylesheet is inlined into each page's HTML<style>and also serialized into the page's RSC payloads — the inline flight inside the.html, thepage.rsc, and each.segments/*.segment.rsc.Observed in the repro for one trivial static page (
a1.html, 411 KB for "tiny content"): 1<style>block, but the CSS marker rule appears 3× (<style>+ flight). Across the build the 155 KB CSS is embedded in 62.html, 186.rsc(of which 124 are*.segments/*.segment.rsc) →.next/server/app= 69 MB for 60 pages of "tiny content". So each prerendered page stores the stylesheet ~3–4× (HTML<style>+ HTML flight +page.rsc+ eachsegment.rsc); build output scales withCSS_size × pages × ~4.Amplifier: moving the
@importfrom the root layout into a nested layout (route group) makes the per-segment copies multiply (~2× → ~5× per page in a larger app), so per-route CSS scoping is counter-productive underinlineCss. On a real content site (~700 prerendered pages, 172 KB CSS) the duplicated CSS is ~205 MB of a 453 MBserver/app; moving CSS to a nested layout tookserver/appfrom 453 MB to 868 MB.Expected: inlined CSS referenced/deduplicated once per prerendered page rather than copied into every RSC/segment payload. The segment-cache / client-navigation RSC payloads don't need the full stylesheet embedded — on client navigation the browser already has the styles applied. Keep inlining into the initial HTML (the FCP/LCP win) without duplicating across the RSC.
Provide environment information
Which area(s) are affected? (Select all that apply)
Output (Standalone), Partial Prerendering (PPR)
Which stage(s) are affected? (Select all that apply)
next build (local)
Additional context
inlineCssis otherwise a real FCP/LCP win, so disabling it is an unwanted trade-off — the request is to keep the initial-HTML inline but stop duplicating the bundle across the RSC/segment payloads. Measured viadu+ counting the inlined CSS chunk across.html/.rsc/.segments/*.segment.rsc. (Supersedes #95140, which was auto-closed for a parsing issue — the reproduction link is now in the correct field.)