[Turbopack] Shared library CSS module duplicated & re-ordered after client navigation in dev, breaking cascade order
Nobody has claimed this yet.
- 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/ilchenkoArtem/turbopack-css-order-repro
To Reproduce
npm installnpm run dev(runsnx serve web→next dev --turbopack, App Router)- Open the home page. The "Show more" button is transparent (white border, white text) — correct.
- Click the button → client navigation to
/catalog. - Press the browser Back button.
- The button is now orange — wrong.
Current vs. Expected behavior
A shared Button component lives in a separate library (libs/ui-kit, imported via the @ui-kit/* tsconfig path alias + experimental.externalDir, built through @nx/next's withNx). Its .kindPrimary class sets --btn-bg: #fd9728 (orange). The app's Banner adds .featureButton which overrides --btn-bg: transparent. Both selectors have specificity (0,1,0), so the cascade is decided purely by document order, and the override is authored to win by coming later.
Current: On the client navigation to /catalog, Turbopack loads a second copy of the shared Button stylesheet (e.g. _0fllvkn._.css) and appends it to <head>. On Back this duplicate is not removed, so it ends up after the home chunk that contains .featureButton. The later .kindPrimary now wins → the button turns orange.
DOM after Back (both stylesheets define --btn-bg):
_12prpzp._.css .button {…} .kindPrimary {--btn-bg:#fd9728} .featureButton {--btn-bg:transparent}
_0fllvkn._.css .button {…} .kindPrimary {--btn-bg:#fd9728} ← appended on nav, not removed → wins
Expected: CSS module cascade order stays stable across client navigations (as it does under webpack), so the override keeps winning and the button stays transparent.
This is incorrect styling in next dev only, surfaced by client-side navigation. A hard reload of the same URL renders correctly. (Distinct from #83941, which reports a dev-vs-next build discrepancy; here next dev itself renders the wrong order after a soft navigation.)
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.3.0
Available memory (MB): 36864
Available CPU cores: 12
Binaries:
Node: 22.15.1
npm: 10.9.2
pnpm: 10.15.0
Relevant Packages:
next: 16.2.3 (also reproduced on 16.2.9 and 16.3.0-canary.58)
react: 19.2.7
react-dom: 19.2.7
typescript: 5.9.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Turbopack
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
- Open the repro in CodeSandbox (Devbox — runs real Turbopack): https://codesandbox.io/p/github/ilchenkoArtem/turbopack-css-order-repro
- Reproduced on
next@16.2.3,16.2.9, and the latest canary16.3.0-canary.58. - Conditions required to trigger (each matters):
- Built through
@nx/next'swithNx(this is an Nx monorepo). Plainnext devin a single-package app batches the CSS into one chunk and does not reproduce. - The shared component is outside the app dir (
libs/ui-kit, reached via path alias +experimental.externalDir), so its CSS module is emitted as a standalone chunk. - Enough routes share the component that Turbopack gives it its own chunk (
/r1..r16+/catalogin the repro).
- Built through
- Workaround (not a fix): raising the override's specificity to
(0,2,0)(.featureButton.featureButton) makes it win regardless of chunk order. The underlying issue is that equal-specificity CSS-module ordering is not preserved across client navigations under Turbopack. - Replaces #94978, which was auto-closed because its reproduction section contained more than one link; same repro, link corrected. Likely related to #83941 and PR #89615.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked turbopack-css-order-repro: run npm install, npm run dev, navigate home → /catalog → Back, and inspect the generated stylesheets in the document head. Trace Turbopack's CSS chunk handling during client navigation; done means the shared stylesheet is not duplicated or left appended, and equal-specificity cascade order remains stable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css, javascript, next.js, react
- Domain
- build-system, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100