Skip to content

feat: add SSR remote cache clearing#4824

Open
2heal1 wants to merge 6 commits into
mainfrom
feat/mf-ssr-clear-cache
Open

feat: add SSR remote cache clearing#4824
2heal1 wants to merge 6 commits into
mainfrom
feat/mf-ssr-clear-cache

Conversation

@2heal1

@2heal1 2heal1 commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary

  • add removeRemote as a public runtime API and lifecycle hook
  • install webpack bundler runtime cache clearing through a runtime plugin
  • clear stale remote, chunk, entry, shared, and runtime caches so the next SSR load can use the current remote
  • add focused runtime and bundler runtime tests

Validation

  • pnpm --filter @module-federation/runtime-core test -- register-remotes.spec.ts
  • pnpm --filter @module-federation/runtime test -- api.spec.ts
  • pnpm --filter @module-federation/webpack-bundler-runtime test -- clearCache.spec.ts
  • pnpm --filter @module-federation/runtime-core build
  • pnpm --filter @module-federation/runtime build
  • pnpm --filter @module-federation/webpack-bundler-runtime build

Note: these commands were run with Node v22.22.2; the repo warns that it expects Node ^20.

Memory validation

Local SSR memory repro:

  1. Start the four apps from the repo root:
pnpm --dir apps/modernjs-ssr/nested-remote dev
pnpm --dir apps/modernjs-ssr/remote dev
pnpm --dir apps/modernjs-ssr/remote-new-version dev
pnpm --dir apps/modernjs-ssr/host dev

The host dev script starts Node with --expose-gc, so the page can trigger GC before collecting memory rows.

  1. Open the full flow:
http://localhost:3050/remove-remote-cache

Expected checks:

  • heavy version is v1
  • reloaded heavy version is v2
  • after load heap MB is higher than before load
  • after gc or one delayed GC row is lower than after removeRemote
  • after reload rises again after loading remote v2
  1. If heap snapshots are needed, start the host with snapshots enabled while the remotes above are still running:
MF_SSR_HEAP_SNAPSHOT=all \
MF_SSR_HEAP_SNAPSHOT_DIR=/tmp/mf-ssr-cache-probe \
pnpm --dir apps/modernjs-ssr/host dev

Then open the same route and load the generated .heapsnapshot files in Chrome DevTools Memory. Compare later snapshots against before load, and search for remote-heavy, remote-heavy-v2, Heavy, or remote/Heavy to inspect retained objects and retainers.

  1. If the full route is too heavy while snapshots are enabled, use the split routes in order from the same host process:
http://localhost:3050/remove-remote-cache/load-remote
http://localhost:3050/remove-remote-cache/remove-remote
http://localhost:3050/remove-remote-cache/register-new-remote
  1. Automated checks:
node tools/scripts/run-modern-e2e.mjs --mode=manifest
pnpm run probe:modern:ssr-gc -- --iterations=20 --max-growth-mb=20

@netlify

netlify Bot commented Jun 17, 2026

Copy link
Copy Markdown

Deploy Preview for module-federation-docs ready!

Name Link
🔨 Latest commit 47905e2
🔍 Latest deploy log https://app.netlify.com/projects/module-federation-docs/deploys/6a3a093260f1c000083e2060
😎 Deploy Preview https://deploy-preview-4824--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.

@changeset-bot

changeset-bot Bot commented Jun 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 47905e2

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@pkg-pr-new

pkg-pr-new Bot commented Jun 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

@module-federation/devtools

pnpm add https://pkg.pr.new/@module-federation/devtools@47905e2

@module-federation/cli

pnpm add https://pkg.pr.new/@module-federation/cli@47905e2

create-module-federation

pnpm add https://pkg.pr.new/create-module-federation@47905e2

@module-federation/dts-plugin

pnpm add https://pkg.pr.new/@module-federation/dts-plugin@47905e2

@module-federation/enhanced

pnpm add https://pkg.pr.new/@module-federation/enhanced@47905e2

@module-federation/error-codes

pnpm add https://pkg.pr.new/@module-federation/error-codes@47905e2

@module-federation/esbuild

pnpm add https://pkg.pr.new/@module-federation/esbuild@47905e2

@module-federation/managers

pnpm add https://pkg.pr.new/@module-federation/managers@47905e2

@module-federation/manifest

pnpm add https://pkg.pr.new/@module-federation/manifest@47905e2

@module-federation/metro

pnpm add https://pkg.pr.new/@module-federation/metro@47905e2

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

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

@module-federation/metro-plugin-rnef

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

@module-federation/metro-plugin-rock

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

@module-federation/modern-js

pnpm add https://pkg.pr.new/@module-federation/modern-js@47905e2

@module-federation/modern-js-v3

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

@module-federation/native-federation-tests

pnpm add https://pkg.pr.new/@module-federation/native-federation-tests@47905e2

@module-federation/native-federation-typescript

pnpm add https://pkg.pr.new/@module-federation/native-federation-typescript@47905e2

@module-federation/nextjs-mf

pnpm add https://pkg.pr.new/@module-federation/nextjs-mf@47905e2

@module-federation/node

pnpm add https://pkg.pr.new/@module-federation/node@47905e2

@module-federation/observability-plugin

pnpm add https://pkg.pr.new/@module-federation/observability-plugin@47905e2

@module-federation/retry-plugin

pnpm add https://pkg.pr.new/@module-federation/retry-plugin@47905e2

@module-federation/rsbuild-plugin

pnpm add https://pkg.pr.new/@module-federation/rsbuild-plugin@47905e2

@module-federation/rspack

pnpm add https://pkg.pr.new/@module-federation/rspack@47905e2

@module-federation/rspress-plugin

pnpm add https://pkg.pr.new/@module-federation/rspress-plugin@47905e2

@module-federation/runtime

pnpm add https://pkg.pr.new/@module-federation/runtime@47905e2

@module-federation/runtime-core

pnpm add https://pkg.pr.new/@module-federation/runtime-core@47905e2

@module-federation/runtime-tools

pnpm add https://pkg.pr.new/@module-federation/runtime-tools@47905e2

@module-federation/sdk

pnpm add https://pkg.pr.new/@module-federation/sdk@47905e2

@module-federation/storybook-addon

pnpm add https://pkg.pr.new/@module-federation/storybook-addon@47905e2

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

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

@module-federation/treeshake-frontend

pnpm add https://pkg.pr.new/@module-federation/treeshake-frontend@47905e2

@module-federation/treeshake-server

pnpm add https://pkg.pr.new/@module-federation/treeshake-server@47905e2

@module-federation/typescript

pnpm add https://pkg.pr.new/@module-federation/typescript@47905e2

@module-federation/utilities

pnpm add https://pkg.pr.new/@module-federation/utilities@47905e2

@module-federation/webpack-bundler-runtime

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

@module-federation/bridge-react

pnpm add https://pkg.pr.new/@module-federation/bridge-react@47905e2

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

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

@module-federation/bridge-shared

pnpm add https://pkg.pr.new/@module-federation/bridge-shared@47905e2

@module-federation/bridge-vue3

pnpm add https://pkg.pr.new/@module-federation/bridge-vue3@47905e2

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

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

commit: 47905e2

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Report

27 package(s) changed, 14 unchanged.

Package dist + ESM entry

Package Total dist (raw) Delta ESM gzip Delta
@module-federation/bridge-vue3 173.6 kB +1.9 kB (+1.1%) 25.2 kB +264 B (+1.0%)
@module-federation/cli 25.5 kB -893 B (-3.3%) 810 B +24 B (+3.1%)
@module-federation/core 39.1 kB no change 173 B no change
@module-federation/devtools 664.0 kB no change 4.0 kB no change
@module-federation/dts-plugin 313.3 kB +219 B (+0.1%) 4.7 kB no change
@module-federation/enhanced 809.9 kB +502 B (+0.1%) 672 B no change
@module-federation/esbuild 260.8 kB -7636 B (-2.8%) 69 B -47 B (-40.5%)
@module-federation/managers 66.9 kB -2974 B (-4.2%) 244 B -90 B (-26.9%)
@module-federation/manifest 132.6 kB -3521 B (-2.5%) 106 B -76 B (-41.8%)
@module-federation/metro 278.8 kB +1.6 kB (+0.6%) 137 B -10 B (-6.8%)
@module-federation/metro-plugin-rnc-cli 0 B no change 314 B no change
@module-federation/metro-plugin-rnef 8.6 kB +168 B (+1.9%) 108 B -3 B (-2.7%)
@module-federation/metro-plugin-rock 8.6 kB +168 B (+1.9%) 108 B -3 B (-2.7%)
@module-federation/modern-js 197.2 kB +2.8 kB (+1.4%) 1.2 kB no change
@module-federation/modern-js-v3 188.4 kB +2.7 kB (+1.5%) 876 B +1 B (+0.1%)
@module-federation/node 193.4 kB no change 217 B no change
@module-federation/retry-plugin 67.5 kB +219 B (+0.3%) 2.8 kB no change
@module-federation/rsbuild-plugin 116.4 kB -3498 B (-2.9%) 61 B -30 B (-33.0%)
@module-federation/rspack 58.0 kB -2595 B (-4.2%) 161 B -50 B (-23.7%)
@module-federation/rspress-plugin 19.6 kB -327 B (-1.6%) 4.5 kB -3 B (-0.1%)
@module-federation/runtime 20.7 kB +735 B (+3.6%) 729 B +14 B (+2.0%)
@module-federation/runtime-core 290.4 kB +2.7 kB (+0.9%) 477 B no change
@module-federation/treeshake-frontend 629.3 kB -41 B (-0.0%) 0 B no change
@module-federation/treeshake-server 778.5 kB -34288 B (-4.1%) 124 B -8047 B (-98.5%)
@module-federation/utilities 105.4 kB -5308 B (-4.7%) 227 B -101 B (-30.8%)
@module-federation/webpack-bundler-runtime 160.3 kB +62.1 kB (+63.2%) 434 B +29 B (+7.2%)
create-module-federation 11.9 kB -368 B (-2.9%) 3.5 kB -22 B (-0.6%)

Bundle targets

Package Web bundle (gzip) Delta Node bundle (gzip) Delta
@module-federation/bridge-vue3 19.1 kB +208 B (+1.1%) 18.8 kB +211 B (+1.1%)
@module-federation/cli 2.4 kB +6 B (+0.2%) 2.4 kB +6 B (+0.2%)
@module-federation/core 1.1 kB -32 B (-2.8%) 1.1 kB -31 B (-2.8%)
@module-federation/devtools 30.1 kB -19 B (-0.1%) 30.1 kB -20 B (-0.1%)
@module-federation/dts-plugin 14.4 kB no change 14.4 kB no change
@module-federation/enhanced 2.7 kB -21 B (-0.7%) 2.7 kB -20 B (-0.7%)
@module-federation/esbuild 37 B no change 37 B no change
@module-federation/managers 2.4 kB +4 B (+0.2%) 2.4 kB +4 B (+0.2%)
@module-federation/manifest 5.6 kB no change 5.6 kB no change
@module-federation/metro 9.5 kB no change 9.5 kB no change
@module-federation/metro-plugin-rnc-cli 436 B -26 B (-5.6%) 436 B -26 B (-5.6%)
@module-federation/metro-plugin-rnef 592 B no change 597 B no change
@module-federation/metro-plugin-rock 595 B no change 598 B no change
@module-federation/modern-js 4.9 kB +35 B (+0.7%) 4.9 kB +35 B (+0.7%)
@module-federation/modern-js-v3 4.7 kB +29 B (+0.6%) 4.7 kB +29 B (+0.6%)
@module-federation/node 9.3 kB -27 B (-0.3%) 9.3 kB -27 B (-0.3%)
@module-federation/retry-plugin 1.9 kB no change 1.9 kB no change
@module-federation/rsbuild-plugin 4.5 kB no change 4.5 kB no change
@module-federation/rspack 2.7 kB -11 B (-0.4%) 2.7 kB -11 B (-0.4%)
@module-federation/rspress-plugin 3.2 kB +4 B (+0.1%) 3.2 kB +4 B (+0.1%)
@module-federation/runtime 698 B +13 B (+1.9%) 698 B +13 B (+1.9%)
@module-federation/runtime-core 15.5 kB +221 B (+1.4%) 15.2 kB +220 B (+1.4%)
@module-federation/treeshake-frontend n/a n/a n/a n/a
@module-federation/treeshake-server 5.7 kB no change 5.7 kB no change
@module-federation/utilities 2.2 kB +19 B (+0.8%) 2.2 kB +19 B (+0.8%)
@module-federation/webpack-bundler-runtime 7.9 kB +3.9 kB (+96.1%) 7.9 kB +3.9 kB (+96.1%)
create-module-federation 2.5 kB +1 B (+0.0%) 2.5 kB +1 B (+0.0%)

Tree-shakable entrypoints

Package Export Entry gzip Delta Web bundle (gzip) Delta Node bundle (gzip) Delta Gap (node-web) Delta
@module-federation/runtime ./bundler 185 B +8 B (+4.5%) 698 B +13 B (+1.9%) 698 B +13 B (+1.9%) 0 B 0 B
@module-federation/webpack-bundler-runtime ./bundler 151 B no change 7.9 kB +3.9 kB (+96.1%) 7.9 kB +3.9 kB (+96.1%) 0 B 0 B

Consumer scenarios

Scenario Web output (gzip) Delta Node output (gzip) Delta Gap (node-web) Delta
Enhanced remoteEntry 25.2 kB +3.8 kB (+17.8%) 26.3 kB +3.8 kB (+16.8%) +1.0 kB -31 B

Total dist (raw): 6.83 MB (+15.6 kB (+0.2%))
Total ESM gzip: 70.6 kB (-8150 B (-10.1%))
Total web bundle (gzip): 210.1 kB (+4.3 kB (+2.1%))
Total node bundle (gzip): 210.8 kB (+4.3 kB (+2.1%))
Tracked ./bundler entry gzip: 564 B (+8 B (+1.4%))
Tracked ./bundler web bundle (gzip): 8.7 kB (+3.9 kB (+80.9%))
Tracked ./bundler node bundle (gzip): 8.7 kB (+3.9 kB (+80.9%))

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.

Comment thread tools/scripts/probe-modern-ssr-remove-remote-gc.mjs Fixed
Comment thread packages/webpack-bundler-runtime/src/clearCache.ts Fixed
Comment thread packages/webpack-bundler-runtime/src/clearCache.ts Fixed
@2heal1 2heal1 force-pushed the feat/mf-ssr-clear-cache branch 2 times, most recently from ad6c86f to ad3b702 Compare June 23, 2026 02:57
@2heal1 2heal1 force-pushed the feat/mf-ssr-clear-cache branch from ad3b702 to 149dbbd Compare June 23, 2026 03:34
@2heal1 2heal1 marked this pull request as ready for review June 23, 2026 06:14

@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: 47905e2f7a

ℹ️ 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".

if (options?.force) {
// remove registered remote
this.removeRemote(registeredRemote);
void this.removeRemote(registeredRemote);

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 Await removal before validating the replacement remote

When force re-registering a remote with an alias, removeRemote now defers the actual array splice until its promise continuation, so the old remote is still in targetRemotes when normalizeRemote() runs next. The alias-prefix check then matches the existing remote's same alias and throws, so registerRemotes([{ name, alias, ... }], { force: true }) regresses for aliased remotes; the old entry needs to be removed before validating/registering the replacement.

Useful? React with 👍 / 👎.

Comment on lines +1317 to +1319
.catch((error) => {
reportRemoveRemoteClearCacheError(error);
throw error;

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 Do not abort removal when no cache entry exists

In the bundled runtime, this hook runs before RemoteHandler.removeRemote splices the remote from options.remotes. If the remote has not been requested/generated into remotesLoadingData yet, clearCache rejects with the not-found cache error and the rethrow here prevents the remote from being removed at all, even though there was simply no bundler cache to evict. Treat that case as a no-op or otherwise let the runtime removal continue.

Useful? React with 👍 / 👎.

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.

2 participants