Skip to content

Follow-up: Fix RSC streamed component CSS reveal gating to prevent FOUC #4032

Description

@justin808

Context

The RSC/streaming FOUC acceptance tests added in the pending test PR expose a real streamed SSR reveal bug.

These tests intentionally assert user-visible behavior instead of implementation details:

  • If the CSS required by a streamed RSC client boundary is loaded, the component should be visible and styled even if JS is delayed.
  • If that CSS is not loaded yet, the streamed component should not become visible, regardless of whether JS has loaded.

Failing command

cd react_on_rails_pro/spec/dummy &&
pnpm exec playwright test e2e-tests/rsc_fouc.spec.ts --project=chromium --reporter=line

Failing tests

  • streamed RSC content is visible and styled when its CSS is loaded, even while JS is delayed
  • streamed RSC content does not appear before its CSS when JS is available
  • streamed RSC content still waits for CSS if JS finishes first

Observed behavior

  • The streamed RSC HTML is inserted into the page while the component CSS is not applied.
  • With JS delayed, the streamed RSC probe is visible but computed styles remain browser defaults:
    • backgroundColor: rgba(0, 0, 0, 0)
    • borderTopColor: rgb(229, 231, 235)
    • color: rgb(0, 0, 0)
    • CSS sentinel custom property is empty
  • With CSS delayed and JS available, the RSC probe becomes visible before the held CSS response is released.
  • With CSS delayed and JS delayed, releasing JS first still allows the RSC probe to become visible before the held CSS response is released.

The streamed response currently includes a style preload and then swaps the content into the DOM:

<link rel="preload" as="style" href="/webpack/test/css/client1-46072b81.css"/>

That fetches the stylesheet but does not make it an applied stylesheet before the streamed content is revealed.

Evidence

Playwright error contexts from the local run:

  • react_on_rails_pro/spec/dummy/test-results/rsc_fouc-RSC-and-streaming-308b7-ed-even-while-JS-is-delayed-chromium/error-context.md
  • react_on_rails_pro/spec/dummy/test-results/rsc_fouc-RSC-and-streaming-ac4f4-ts-CSS-when-JS-is-available-chromium/error-context.md
  • react_on_rails_pro/spec/dummy/test-results/rsc_fouc-RSC-and-streaming-10b38-or-CSS-if-JS-finishes-first-chromium/error-context.md

Expected behavior matrix

Scenario Expected
Required RSC CSS loaded, JS delayed RSC probe is visible and styled
Required RSC CSS delayed, JS allowed RSC probe is not visible during a stable wait window
Required RSC CSS delayed, JS delayed, then JS released first RSC probe remains hidden until CSS is released
Required RSC CSS released after either delayed scenario RSC probe becomes visible and styled

Pending test reproduction

The pending tests should be runnable with:

cd react_on_rails_pro/spec/dummy &&
REACT_ON_RAILS_RUN_PENDING_FOUC_TESTS=true pnpm exec playwright test e2e-tests/rsc_fouc.spec.ts --project=chromium --reporter=line

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions