Skip to content

fix(next-plugin): prevent incomplete Turbopack production CSS - #633

Merged
owjs3901 merged 2 commits into
mainfrom
owjs3901/fix-turbopack-css-race
Aug 23, 2026
Merged

fix(next-plugin): prevent incomplete Turbopack production CSS#633
owjs3901 merged 2 commits into
mainfrom
owjs3901/fix-turbopack-css-race

Conversation

@owjs3901

@owjs3901 owjs3901 commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • pre-extract every production app source candidate before Turbopack can request its first CSS snapshot
  • discover bare runtime imports and prewarm loader-accepted package entries, including @devup-ui/reset-css
  • seed coordinator completion state from the deterministic prewarmed sheet in both per-file and singleCss modes
  • add regression coverage and patch changepacks for @devup-ui/next-plugin and @devup-ui/plugin-utils

Root cause

The coordinator treated a quiet extraction window as a Turbopack compilation-complete signal. A CSS request could arrive between source-loader waves and freeze an incomplete snapshot. This scheduling race affects both CSS modes; singleCss: true exposed it consistently because the first shared stylesheet was missing the reset CSS layer, including box-sizing: border-box.

The initial route-closure prewarm removed the late app-loader race, but the reset package is compiled from outside the app src directory and therefore was still absent from that set. Production prewarming now includes every extractable app source candidate and accepted external package entry using the same WASM filename and options as loader-time extraction. Loader extraction remains idempotent, while development behavior is unchanged.

Failed run: https://github.com/dev-five-git/devup-ui/actions/runs/32644170599/job/97205722867
Passing run: https://github.com/dev-five-git/devup-ui/actions/runs/32650834331

Follow-up to #399.

Verification

  • full repository lint
  • 5,135 Bun tests with 100% TypeScript function and line coverage
  • focused next-plugin/plugin-utils regression suite: 128 passing
  • local Landing production E2E: 108/108 with singleCss: false
  • local Landing production E2E: 108/108 with singleCss: true
  • GitHub Actions benchmark and publish jobs passed, including both Landing E2E modes and changepacks validation

@github-actions

Copy link
Copy Markdown
Contributor

Changepacks

@devup-ui/wasm@1.0.75 → 1.0.76 - bindings/devup-ui-wasm/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion

@devup-ui/bun-plugin@1.0.12 → 1.0.13 - packages/bun-plugin/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion

@devup-ui/components@0.1.50 → 0.1.51 - packages/components/package.json

Patch

  • Auto-update: depends on '@devup-ui/react' via a local workspace dependency

@devup-ui/next-plugin@1.0.80 → 1.0.81 - packages/next-plugin/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion
  • Prevent incomplete CSS in Turbopack production builds by prewarming application and external global style entries

@devup-ui/plugin-utils@1.0.10 → 1.0.11 - packages/plugin-utils/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion
  • Prevent incomplete CSS in Turbopack production builds by prewarming application and external global style entries

@devup-ui/react@1.0.37 → 1.0.38 - packages/react/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion

@devup-ui/reset-css@1.0.24 → 1.0.25 - packages/reset-css/package.json

Patch

  • Auto-update: depends on '@devup-ui/react' via a local workspace dependency

@devup-ui/rsbuild-plugin@1.0.58 → 1.0.59 - packages/rsbuild-plugin/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion

@devup-ui/vite-plugin@1.0.64 → 1.0.65 - packages/vite-plugin/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion

@devup-ui/webpack-plugin@1.0.63 → 1.0.64 - packages/webpack-plugin/package.json

Patch

  • Add plugin-configured custom shorthands with generated TypeScript completion

@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
packages/next-plugin/src/coordinator.ts 100.00% <100.00%> (ø)
packages/next-plugin/src/plugin.ts 100.00% <100.00%> (ø)
packages/next-plugin/src/prewarm.ts 100.00% <100.00%> (ø)
packages/plugin-utils/src/import-graph.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@owjs3901
owjs3901 merged commit 4614ab2 into main Aug 23, 2026
3 checks passed
Archibald1948 pushed a commit to Archibald1948/devup-ui that referenced this pull request Aug 24, 2026
The landing app is the repository's only real-scale acceptance target, and
migrating it to vinext left `@devup-ui/next-plugin`'s Turbopack production
CSS path with no e2e coverage at all. That path's last regression (dev-five-git#633)
only reproduced across a 64-route build's extraction waves, so a toy app
cannot replace it.

Build the same sources with both bundlers and run the same 128 assertions
and the same screenshot baselines against each artifact. vinext still
produces the deployed output; the Next build is CI-only.

- replace `import.meta.glob` demo discovery with a barrel generated by
  `script.js`, so the demo graph is statically visible to Turbopack and
  Vite alike instead of to only one of them
- resolve the artifact root and the not-found manifest from
  LANDING_BUILD_MODE, and teach the static server Next's nested
  segment-cache payload layout
- restore the Next toolchain behind `build:next`, which drops
  `deploymentId` (Next reads it as skew protection and hard-navigates when
  a static host cannot echo it) and skips the vinext-only RSC transport
- give the local-asset sweep a stated budget and a bounded request pool;
  it takes ~4s alone but starved past 60s against the route-render tests
- run the Next pair in a parallel `landing-next-e2e` job

Verified locally, 128/128 in all four combinations: vinext and Next, each
with default and DEVUP_SINGLE_CSS=1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant