Repository navigation
Conversation
🦋 Changeset detectedLatest commit: b64085e The changes in this PR will be included in the next version bump. This PR includes changesets to release 48 packages
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 |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
@module-federation/devtools
@module-federation/cli
create-module-federation
@module-federation/dts-plugin
@module-federation/enhanced
@module-federation/error-codes
@module-federation/esbuild
@module-federation/managers
@module-federation/manifest
@module-federation/metro
@module-federation/metro-plugin-rnc-cli
@module-federation/metro-plugin-rnef
@module-federation/metro-plugin-rock
@module-federation/modern-js
@module-federation/modern-js-v3
@module-federation/native-federation-tests
@module-federation/native-federation-typescript
@module-federation/nextjs-mf
@module-federation/node
@module-federation/observability-plugin
@module-federation/playground
@module-federation/retry-plugin
@module-federation/rsbuild-plugin
@module-federation/rspack
@module-federation/rspress-plugin
@module-federation/rstest
@module-federation/runtime
@module-federation/runtime-core
@module-federation/runtime-tools
@module-federation/sdk
@module-federation/storybook-addon
@module-federation/third-party-dts-extractor
@module-federation/treeshake-frontend
@module-federation/treeshake-server
@module-federation/typescript
@module-federation/utilities
@module-federation/webpack-bundler-runtime
@module-federation/bridge-react
@module-federation/bridge-react-webpack-plugin
@module-federation/bridge-shared
@module-federation/bridge-vue3
@module-federation/inject-external-runtime-core-plugin
commit: |
Bundle Size Report19 package(s) changed, 24 unchanged. Package dist + ESM entry
Bundle targets
Tree-shakable entrypoints
Consumer scenarios
Total dist (raw): 36.50 MB (+349.9 kB (+0.9%)) Bundle sizes are generated with rslib (Rspack). Package-root metrics preserve the historical report. Tracked subpath exports such as |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7d503c1868
ℹ️ 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 (hasActiveSharedConsumers(target)) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Evict non-shared caches when retaining a shared provider
When the removed provider has a loaded shared dependency consumed by another runtime—a common case for React or antd—this return skips deletion of its remote-module factories, wrapper modules, chunks, and entry cache. Direct removeRemote subsequently cleans only the core module cache, while the forced-registration wrapper performs no later cleanup at all, so non-shared exposes can remain reachable or a forced replacement can continue serving the old implementation. Retain the active shared record without bypassing eviction of the provider's unrelated modules.
Useful? React with 👍 / 👎.
| 'for(var moduleId in moduleCache) {', | ||
| Template.indent([ | ||
| `${RuntimeGlobals.hasOwnProperty}(moduleCache, moduleId) && delete moduleCache[moduleId];`, |
There was a problem hiding this comment.
Avoid clearing the container's entire module cache
When a remote entry shares its webpack runtime with another entrypoint or with its own running application, invoking __webpack_clear_cache__ deletes every initialized module in that compilation, not just modules belonging to the removed exposes. Unrelated stateful modules will therefore be re-executed on their next require, potentially duplicating application initialization and singleton state; the hook needs to target only modules owned by the container/exposes.
Useful? React with 👍 / 👎.
| if (!options?.force) { | ||
| return originalRegisterRemotes(remotes as any, options as any); | ||
| } | ||
| return registerRemotesWithForce(webpackRequire, instance, remotes); |
There was a problem hiding this comment.
Emit removal hooks during forced registration
With the bundler runtime installed, every registerRemotes(..., { force: true }) call takes this replacement path instead of the core implementation, and registerRemotesWithForce never emits the newly added removeRemote lifecycle hook. Runtime plugins that release provider-specific resources in that hook work for explicit removal but are silently bypassed for forced replacement, despite the core path defining replacement as removal followed by registration.
Useful? React with 👍 / 👎.
| export function removeRemote( | ||
| ...args: Parameters<ModuleFederation['removeRemote']> | ||
| ): ReturnType<ModuleFederation['removeRemote']> { | ||
| assert(FederationInstance, RUNTIME_009, runtimeDescMap); | ||
| // eslint-disable-next-line prefer-spread | ||
| return FederationInstance.removeRemote.apply(FederationInstance, args); |
There was a problem hiding this comment.
Add a changeset for the published runtime behavior
This commit adds the public removeRemote API and changes behavior in multiple publishable packages, but the commit contains no .changeset file, so the release plan will not version or publish these changes. Add a changeset covering the affected packages as required by the repository release policy.
AGENTS.md reference: AGENTS.md:L221-L227
Useful? React with 👍 / 👎.
| function loadFrames() { | ||
| const url = state.hosts[selected].url; | ||
| $('old').src = url + '/'; | ||
| $('new').src = url + $('entry').value; |
| frame = document.createElement('iframe'); | ||
| frame.id = 'traffic-preview'; | ||
| frame.title = '更新期间发起的真实 SSR 页面请求'; | ||
| frame.src = host.url + visit.entry + '?id=iframe-' + exp.started; |
| }); | ||
| $('reload').onclick = () => { | ||
| $('new').src = | ||
| state.hosts[selected].url + $('entry').value + '?t=' + Date.now(); |
| res.end('Control API only'); | ||
| } catch (e) { | ||
| res.writeHead(500); | ||
| res.end(JSON.stringify({ error: String(e) })); |
| res.end('Control API only'); | ||
| } catch (e) { | ||
| res.writeHead(500); | ||
| res.end(JSON.stringify({ error: String(e) })); |
| return Response.json(result); | ||
| } catch (e) { | ||
| console.error(e); | ||
| return new Response(String(e.stack), { status: 500 }); |
| res.end(await fs.readFile(path.join(dir, file))); | ||
| } catch (e) { | ||
| res.writeHead(500); | ||
| res.end(JSON.stringify({ error: String(e) })); |
| res.end(await fs.readFile(path.join(dir, file))); | ||
| } catch (e) { | ||
| res.writeHead(500); | ||
| res.end(JSON.stringify({ error: String(e) })); |
Description
Updating an SSR remote must invalidate both its MF state and the host modules that retain its exports. This PR adds explicit remote replacement and connects cache invalidation to Modern's SSR lifecycle: statically owned dependencies use selective entry updates; dynamic or unprovable dependencies rebuild the SSR application in the same process. Incoming requests wait within the affected scope, and new SSR responses and hydration use the selected release.
Cross-repository implementation
updateRemotes, deprecate force registration, and coordinate remote/container cleanup with bound bundler runtimes. Invalidate affected host consumers while preserving live shared dependency closures; dispose obsolete runtime bindings. The Modern adapter maps compiled ownership to SSR entries, handles serialized revisions and batch updates, selects selective/full publication, and supplies release information for hydration.feat/mf-ssr-clear-cache; a branch-to-main umbrella PR was not found at the time of this update.Observable behavior
Updating Remote A reinitializes its affected host entry. With selective updates, an independent B entry keeps its module identity and continues serving requests; with application-wide rebuilding, B is also reinitialized and waits during publication. Neither path restarts the Node process. Partial scope is expanded when entries share a runtime, and incomplete dependency evidence falls back to application rebuilding.
SSR application rebuilding is runtime resource loading, not a fresh Rspack compilation. It does not automatically undo arbitrary business globals, listeners or background tasks.
Validation and remaining integration work
Recorded validation covers runtime/bundler cache cleanup, shared identity retention, stale loads, actual compiled selective/full SSR updates, revisions and batch publication, hydration, bounded queues/timeouts, and repeated-update memory sampling. The latest independent browser E2E also verifies B's retained/recreated module identity and unchanged PID. Exact commands and validation boundaries are recorded in VALIDATION.md.
The acceptance setup pins MF
0.0.0-feat-mf-ssr-clear-cache-20260914081229, Modern0.0.0-canary-20260914082926and Rspack2.2.3-canary-fde17bab-20260911103204. It still applies the Modern duplicate-pipe fix from #8872 as a pnpm patch, and disables server splitChunks in the MPA fixtures because the tested shared-entry output failed initialization. The new sibling demo has an independent E2E entry and has not replaced the existing SSR CI entry. These are retained integration limits, not claims of completed release readiness; full current-head validation remains required before merging to main.Demo guide (中文)
Related Issue
Cross-repository implementation PRs are linked above. No separate issue is linked.
Types of changes
Registration compatibility note: duplicate registration no longer serves as an update path; callers should migrate to
updateRemotes. The branch includes a breaking-change commit for this API transition.Checklist
The full-suite checkbox remains unchecked pending current-head integration validation; recorded passing checks are described above.