Skip to content

fix(bridge-react): dedupe SSR stylesheet assets#4852

Open
BleedingDev wants to merge 10 commits into
module-federation:mainfrom
BleedingDev:codex/fix-bridge-css-dedupe
Open

fix(bridge-react): dedupe SSR stylesheet assets#4852
BleedingDev wants to merge 10 commits into
module-federation:mainfrom
BleedingDev:codex/fix-bridge-css-dedupe

Conversation

@BleedingDev

Copy link
Copy Markdown
Contributor

Summary

  • skip bridge React stylesheet asset nodes during hydration when the same stylesheet href is already present in document.head
  • keep server-side collectSSRAssets output unchanged
  • preserve plain bridge SSR body-owned stylesheet rendering when no head stylesheet exists
  • add a patch changeset for @module-federation/bridge-react

Why

Modern/UltraModern stream SSR already emits federated remote stylesheet links into the document head. The bridge createLazyComponent path then rendered the same stylesheet hrefs again during hydration, producing duplicate remote CSS links. This fixes the resource emitter instead of adding app-level shims.

Validation

  • pnpm install --frozen-lockfile
  • pnpm exec prettier --check .
  • pnpm exec turbo run build --filter=@module-federation/bridge-react... --concurrency=4
  • pnpm --filter @module-federation/bridge-react run test
  • Tractor stream SSR repro with local packed @module-federation/bridge-react tarball:
    • pnpm build
    • ULTRAMODERN_PUBLIC_URL_SHELL_SUPER_APP=http://localhost:3020 pnpm proof:workflow --out .codex/reports/bridge-css-dedupe-workflow-proof.json
    • Browser DOM assertion on /en/tractors and tractor detail route: all hydrated stylesheet hrefs were unique and remained in HEAD

Notes

The initial bridge-react test command failed before running tests because workspace dependencies had not been built in the new worktree. After building @module-federation/bridge-react dependencies through Turbo, the same bridge-react test suite passed.

@changeset-bot

changeset-bot Bot commented Jun 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5dee11e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 47 packages
Name Type
@module-federation/bridge-react Patch
@module-federation/modern-js-v3 Patch
@module-federation/modern-js Patch
@module-federation/playground Patch
remote5 Patch
remote6 Patch
shared-tree-shaking-with-server-host Patch
shared-tree-shaking-with-server-provider Patch
@module-federation/runtime Patch
@module-federation/enhanced Patch
@module-federation/rspack Patch
@module-federation/webpack-bundler-runtime Patch
@module-federation/sdk Patch
@module-federation/runtime-tools Patch
@module-federation/managers Patch
@module-federation/manifest Patch
@module-federation/dts-plugin Patch
@module-federation/third-party-dts-extractor Patch
@module-federation/devtools Patch
@module-federation/bridge-vue3 Patch
@module-federation/bridge-shared Patch
@module-federation/bridge-react-webpack-plugin Patch
@module-federation/retry-plugin Patch
@module-federation/rsbuild-plugin Patch
@module-federation/error-codes Patch
@module-federation/inject-external-runtime-core-plugin Patch
@module-federation/runtime-core Patch
create-module-federation Patch
@module-federation/cli Patch
@module-federation/rspress-plugin Patch
@module-federation/treeshake-server Patch
@module-federation/treeshake-frontend Patch
@module-federation/metro Patch
@module-federation/metro-plugin-rnef Patch
@module-federation/metro-plugin-rock Patch
@module-federation/metro-plugin-rnc-cli Patch
@module-federation/esbuild Patch
@module-federation/nextjs-mf Patch
@module-federation/node Patch
@module-federation/observability-plugin Patch
website-new Patch
@module-federation/storybook-addon Patch
shared-tree-shaking-no-server-host Patch
shared-tree-shaking-no-server-provider Patch
@module-federation/utilities Patch
node-dynamic-remote-new-version Patch
node-dynamic-remote Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify

netlify Bot commented Jun 27, 2026

Copy link
Copy Markdown

Deploy Preview for module-federation-docs ready!

Name Link
🔨 Latest commit b63d4e5
🔍 Latest deploy log https://app.netlify.com/projects/module-federation-docs/deploys/6a4b1e90da5cdf0008710288
😎 Deploy Preview https://deploy-preview-4852--module-federation-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@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: ea661989ac

ℹ️ 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 thread packages/bridge/bridge-react/src/lazy/createLazyComponent.tsx Outdated

@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: 88def799e6

ℹ️ 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 thread .changeset/clean-bridge-css-hydration.md
@pkg-pr-new

pkg-pr-new Bot commented Jul 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

@module-federation/devtools

pnpm add https://pkg.pr.new/@module-federation/devtools@5dee11e

@module-federation/cli

pnpm add https://pkg.pr.new/@module-federation/cli@5dee11e

create-module-federation

pnpm add https://pkg.pr.new/create-module-federation@5dee11e

@module-federation/dts-plugin

pnpm add https://pkg.pr.new/@module-federation/dts-plugin@5dee11e

@module-federation/enhanced

pnpm add https://pkg.pr.new/@module-federation/enhanced@5dee11e

@module-federation/error-codes

pnpm add https://pkg.pr.new/@module-federation/error-codes@5dee11e

@module-federation/esbuild

pnpm add https://pkg.pr.new/@module-federation/esbuild@5dee11e

@module-federation/managers

pnpm add https://pkg.pr.new/@module-federation/managers@5dee11e

@module-federation/manifest

pnpm add https://pkg.pr.new/@module-federation/manifest@5dee11e

@module-federation/metro

pnpm add https://pkg.pr.new/@module-federation/metro@5dee11e

@module-federation/metro-plugin-rnc-cli

pnpm add https://pkg.pr.new/@module-federation/metro-plugin-rnc-cli@5dee11e

@module-federation/metro-plugin-rnef

pnpm add https://pkg.pr.new/@module-federation/metro-plugin-rnef@5dee11e

@module-federation/metro-plugin-rock

pnpm add https://pkg.pr.new/@module-federation/metro-plugin-rock@5dee11e

@module-federation/modern-js

pnpm add https://pkg.pr.new/@module-federation/modern-js@5dee11e

@module-federation/modern-js-v3

pnpm add https://pkg.pr.new/@module-federation/modern-js-v3@5dee11e

@module-federation/native-federation-tests

pnpm add https://pkg.pr.new/@module-federation/native-federation-tests@5dee11e

@module-federation/native-federation-typescript

pnpm add https://pkg.pr.new/@module-federation/native-federation-typescript@5dee11e

@module-federation/nextjs-mf

pnpm add https://pkg.pr.new/@module-federation/nextjs-mf@5dee11e

@module-federation/node

pnpm add https://pkg.pr.new/@module-federation/node@5dee11e

@module-federation/observability-plugin

pnpm add https://pkg.pr.new/@module-federation/observability-plugin@5dee11e

@module-federation/playground

pnpm add https://pkg.pr.new/@module-federation/playground@5dee11e

@module-federation/retry-plugin

pnpm add https://pkg.pr.new/@module-federation/retry-plugin@5dee11e

@module-federation/rsbuild-plugin

pnpm add https://pkg.pr.new/@module-federation/rsbuild-plugin@5dee11e

@module-federation/rspack

pnpm add https://pkg.pr.new/@module-federation/rspack@5dee11e

@module-federation/rspress-plugin

pnpm add https://pkg.pr.new/@module-federation/rspress-plugin@5dee11e

@module-federation/runtime

pnpm add https://pkg.pr.new/@module-federation/runtime@5dee11e

@module-federation/runtime-core

pnpm add https://pkg.pr.new/@module-federation/runtime-core@5dee11e

@module-federation/runtime-tools

pnpm add https://pkg.pr.new/@module-federation/runtime-tools@5dee11e

@module-federation/sdk

pnpm add https://pkg.pr.new/@module-federation/sdk@5dee11e

@module-federation/storybook-addon

pnpm add https://pkg.pr.new/@module-federation/storybook-addon@5dee11e

@module-federation/third-party-dts-extractor

pnpm add https://pkg.pr.new/@module-federation/third-party-dts-extractor@5dee11e

@module-federation/treeshake-frontend

pnpm add https://pkg.pr.new/@module-federation/treeshake-frontend@5dee11e

@module-federation/treeshake-server

pnpm add https://pkg.pr.new/@module-federation/treeshake-server@5dee11e

@module-federation/typescript

pnpm add https://pkg.pr.new/@module-federation/typescript@5dee11e

@module-federation/utilities

pnpm add https://pkg.pr.new/@module-federation/utilities@5dee11e

@module-federation/webpack-bundler-runtime

pnpm add https://pkg.pr.new/@module-federation/webpack-bundler-runtime@5dee11e

@module-federation/bridge-react

pnpm add https://pkg.pr.new/@module-federation/bridge-react@5dee11e

@module-federation/bridge-react-webpack-plugin

pnpm add https://pkg.pr.new/@module-federation/bridge-react-webpack-plugin@5dee11e

@module-federation/bridge-shared

pnpm add https://pkg.pr.new/@module-federation/bridge-shared@5dee11e

@module-federation/bridge-vue3

pnpm add https://pkg.pr.new/@module-federation/bridge-vue3@5dee11e

@module-federation/inject-external-runtime-core-plugin

pnpm add https://pkg.pr.new/@module-federation/inject-external-runtime-core-plugin@5dee11e

commit: 5dee11e

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Report

8 package(s) changed, 34 unchanged.

Package dist + ESM entry

Package Total dist (raw) Delta ESM gzip Delta
@module-federation/bridge-react 298.6 kB +8.7 kB (+3.0%) 1.3 kB +2 B (+0.2%)
@module-federation/playground 28.86 MB +25.6 kB (+0.1%) 44.8 kB +1.1 kB (+2.6%)

Bundle targets

Package Web bundle (gzip) Delta Node bundle (gzip) Delta
@module-federation/bridge-react 12.9 kB +735 B (+5.9%) 13.9 kB +712 B (+5.3%)
@module-federation/cli 2.3 kB -1 B (-0.0%) 2.4 kB -33 B (-1.3%)
@module-federation/core 1.0 kB -3 B (-0.3%) 1.0 kB -34 B (-3.1%)
@module-federation/devtools 30.3 kB -1 B (-0.0%) 30.3 kB -25 B (-0.1%)
@module-federation/enhanced 2.7 kB +11 B (+0.4%) 2.8 kB -45 B (-1.6%)
@module-federation/metro-plugin-rnc-cli 416 B -1 B (-0.2%) 435 B -27 B (-5.8%)
@module-federation/node 9.2 kB no change 9.2 kB -31 B (-0.3%)
@module-federation/playground 40.6 kB +1.1 kB (+2.8%) 40.6 kB +1.1 kB (+2.8%)

Consumer scenarios

Scenario Web output (gzip) Delta Node output (gzip) Delta Gap (node-web) Delta
Enhanced remoteEntry 21.4 kB -10 B (-0.0%) 23.1 kB -25 B (-0.1%) +1.7 kB -15 B

Total dist (raw): 35.82 MB (+34.3 kB (+0.1%))
Total ESM gzip: 106.0 kB (+1.1 kB (+1.1%))
Total web bundle (gzip): 234.9 kB (+1.8 kB (+0.8%))
Total node bundle (gzip): 237.6 kB (+1.6 kB (+0.7%))
Tracked ./bundler entry gzip: 556 B (no change)
Tracked ./bundler web bundle (gzip): 4.8 kB (no change)
Tracked ./bundler node bundle (gzip): 4.8 kB (no change)

Bundle sizes are generated with rslib (Rspack). Package-root metrics preserve the historical report. Tracked subpath exports such as ./bundler are measured separately so ENV_TARGET-driven tree-shaking is visible. Bare imports are externalized to keep package-level sizes consistent, and assets are emitted as resources.

@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: cb30b48f64

ℹ️ 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 thread packages/bridge/bridge-react/src/lazy/createLazyComponent.tsx Outdated
@ScriptedAlchemy

Copy link
Copy Markdown
Member

@2heal Could you please review this when you have a chance? I addressed the concerns raised on the PR and did some refactoring around SSR stylesheet ownership and deduplication. The focused and package test suites pass, and CI is green.

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed the updated implementation and regression coverage. The stylesheet ownership refactor addresses the outstanding concerns, and the relevant checks are green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants