vercel / vercel/next.js

experimental.inlineCss: stylesheet duplicated twice in the flight payload — _full.segment.rsc carries the CSS text 2x (3x total per prerendered page)

Open
#98,079 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

CSS Runtime Turbopack
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Link to the code that reproduces this issue

https://github.com/TulmansMeubelen/next-inlinecss-flight-duplication-repro

To Reproduce
  1. npm install
  2. npm run build (next build --turbopack)
  3. node count.mjs — counts occurrences of the CSS marker (@layer properties) in the build artifacts

The repro is intentionally tiny: a root layout importing one global stylesheet, one app/[locale]/page.tsx with generateStaticParams, and experimental: { inlineCss: true }.

Current vs. Expected behavior

Current (both 16.3.1 and 16.4.0-canary.12):

artifact copies of the CSS text
.next/server/app/nl.html 3 (1 <style> + 2 flight rows)
.next/server/app/nl.rsc 2
.next/server/app/nl.segments/_full.segment.rsc 2
.next/server/app/nl.segments/_index.segment.rsc 1
every other segment file 0

The two flight copies are byte-identical T-rows, each referenced by its own hoistable style element row (["$","style","1",{"precedence":"next","href":"<chunk>.css","children":"$<id>"}]). Both land in the first flushes of the stream. Since the individual segments together only carry one copy, the second copy appears when the full flight (_full.segment.rsc) is assembled — the assembly re-serializes the hoistable stylesheet instead of reusing the already-emitted row.

Expected: at most one copy of the CSS text in the flight payload — the inlineCss docs describe exactly one RSC-payload copy as the known trade-off ("Styles are duplicated during initial page load - once within <style> tags for SSR and once in the RSC payload"), i.e. 2 copies per document, not 3.

Provide environment information
Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 11 Pro
  Available memory (MB): 32679
  Available CPU cores: 16
Binaries:
  Node: 24.11.1
  npm: 11.6.2
Relevant Packages:
  next: 16.4.0-canary.12 (also reproduced on 16.3.1)
  react: 19.2.8
  react-dom: 19.2.8
  typescript: 7.0.2
Which area(s) are affected? (Select all that apply)

CSS, Turbopack, Runtime

Additional context

On a real Tailwind application the inlined stylesheet is large (ours is 249 KB), so the extra flight copy is expensive: every prerendered/ISR-written HTML document carries ~500 KB of flight CSS on top of the 255 KB <style> block. On Vercel this roughly triples ISR write units and fast origin transfer for HTML documents (we measured a content page at 1,174 KB with the flag vs 415 KB without; the third copy alone is ~250 KB per page). Deduplicating the flight copy would remove ~21% of every prerendered page at no functional cost.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run npm install, npm run build, and node count.mjs in the linked reproduction. Compare .next/server/app/nl.rsc and _full.segment.rsc with the individual segment files, then trace how the full flight is assembled. Done means the CSS marker occurs at most once in the RSC payload while the reproduction still builds successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, next.js, react, typescript
Domain
build-system, performance, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.