Skip to content

fix: retain content-addressed development CSS assets - #154

Merged
ScriptedAlchemy merged 6 commits into
mainfrom
codex/fix-css-preload-restoration
Sep 29, 2026
Merged

ScriptedAlchemy merged 6 commits into
mainfrom
codex/fix-css-preload-restoration

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #153.

Restoring a CSS file to its original contents could make the browser reuse edited CSS from its preload cache. This change gives each version of development CSS a content-addressed URL and retains earlier assets so existing manifests keep serving the same bytes.

Changes

  • Update entry and route stylesheets through committed manifests once HMR is idle. Replay the last committed manifest on reconnect.
  • Remove the CSS-manifest exemption from compiler pairing. Keep the last-good server build and browser manifest together until matching compiler results arrive.
  • Disable extract-loader fallback HMR where Router owns development stylesheet updates, so it cannot remove React-owned links. Native async CSS HMR remains enabled.
  • Add browser regressions for plain CSS and Vanilla Extract restoration, plus request-level tests for loader data and stylesheet consistency.
  • Include a patch Changeset. Production and RSC alias emission are unchanged.

Validation

The build, workspace typechecks, all 849 core tests, and all five CSS/HMR/HDR browser regressions pass locally on d91d6c8. This head also covers clients that connect before the first manifest commits.

All nine CI checks passed on d91d6c8, including the full framework and example-app end-to-end suites, package validation, CodeQL, and benchmarks.

The restoration regressions check stylesheet contents, preserved form state, and browser errors. Six request-level regressions fail with the original compiler-pairing bypass and pass with this fix.

Temporary workaround

Remove devCssOwnershipPlugin once every supported Rspack version includes the stylesheet-ownership fix. Re-run the restoration and async CSS HMR tests before removing it. Immutable CSS URLs and compiler pairing are still required.

Development CSS aliases remain on disk until output cleanup or restart. Server-runtime reuse and on-demand SSR compilation remain separate work in #140 and #155.

@pkg-pr-new

pkg-pr-new Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/rsbuild-plugin-react-router@d91d6c8

commit: d91d6c8

@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark results

Case Base Head Delta
build-256-ssr 1554.4 ms 1558.1 ms +0.2%
dev-48-ssr 677.1 ms 673.1 ms -0.6%

@codspeed

codspeed Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 1 untouched benchmark
⏩ 2 skipped benchmarks1


Comparing codex/fix-css-preload-restoration (d91d6c8) with main (a13d67c)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@ScriptedAlchemy

Copy link
Copy Markdown
Collaborator Author

The CSS CI failure is fixed locally by disabling extract-loader fallback HMR through the NormalModule loader hook only in the web development environment where Router handles committed CSS manifests. No dependency source patch or test skip is used. All 15 CSS/lazy-loading matrix tests pass, including both Vanilla Extract state-preservation cases. Added exact edit/preload/restore coverage for Vanilla Extract; both variants pass. Build, full typechecking, and 844 core tests pass. A broader local HMR run has hit loader-update timeouts and remains under investigation; the PR stays draft while CI and broader validation run.

@ScriptedAlchemy
ScriptedAlchemy marked this pull request as ready for review September 29, 2026 00:32
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-29T00:36:00.533213Z fbcf2a0 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fbcf2a0a84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +318 to +324
const manifest = runtime.getCommittedManifest();
if (
sessions.getActiveBinding() === binding &&
isHmrEnabled() &&
manifest
)
client.send('custom', manifestPayload(manifest));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Replay the first commit to already-connected clients

When a browser reconnects during a dev-server recreation before the initial web/node generation commits, getCommittedManifest() returns undefined, so this callback sends nothing. The first commit also emits no manifest update because both cssManifestChanged and routeManifestMetadataChanged require a previous generation, leaving that client on the old session's manifest until another qualifying edit occurs; this can surface after route-topology restarts as stale routes or CSS. Retain such clients until the first commit or publish that initial commit to connected clients.

Useful? React with 👍 / 👎.

@ScriptedAlchemy
ScriptedAlchemy merged commit c635929 into main Sep 29, 2026
9 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the codex/fix-css-preload-restoration branch September 29, 2026 02:35
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.

Development CSS preload can revive an edited stylesheet after exact restoration

1 participant