Skip to content

fix(runtime-core): sync shared options after dynamic registration - #4950

Open
dmchoi77 wants to merge 2 commits into
module-federation:mainfrom
dmchoi77:fix/runtime-register-shared-options
Open

fix(runtime-core): sync shared options after dynamic registration#4950
dmchoi77 wants to merge 2 commits into
module-federation:mainfrom
dmchoi77:fix/runtime-register-shared-options

Conversation

@dmchoi77

@dmchoi77 dmchoi77 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Description

Summary

ModuleFederation.registerShared() updates the runtime share scope, but does not update instance.options.shared with the newly registered shared entries.

loadShare() uses the shared options from instance.options.shared when resolving a target shared module. As a result, a shared module registered through the public registerShared() API cannot be loaded immediately through loadShare().

This change keeps instance.options.shared synchronized with the complete result returned by SharedHandler.registerShared().

Problem

The current implementation calls SharedHandler.registerShared() but discards its allShareInfos result:

registerShared(shared) {
  this.sharedHandler.registerShared(this.options, {
    ...this.options,
    shared,
  });
}

This leaves the runtime in an inconsistent state:

shareScopeMap  contains the dynamically registered shared module
options.shared   does not contain the dynamically registered shared module

loadShare() then resolves against the stale options.shared state instead of the shared module that was just registered.

Reproduction

const mf = new ModuleFederation({
  name: 'dynamic-shared-host',
  remotes: [],
  shared: {},
});

const sharedFactory = () => ({ name: 'dynamic-shared' });

mf.registerShared({
  'dynamic-shared': {
    version: '1.0.0',
    get: () => Promise.resolve(sharedFactory),
  },
});

await mf.loadShare('dynamic-shared');

After registerShared(), the module is present in shareScopeMap, but the corresponding entry is missing from mf.options.shared. loadShare() therefore cannot resolve the dynamically registered shared module reliably.

Root Cause

SharedHandler.registerShared() already returns the merged shared information as allShareInfos. The initial options formatting path stores this result in options.shared, but the public dynamic registration path does not.

The two paths should maintain the same invariant:

options.shared === the complete set of registered shared options

Related Issue

fixes #4952

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have updated the documentation.

@changeset-bot

changeset-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 68a5ddb

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/runtime-core Patch
@module-federation/nextjs-mf Patch
@module-federation/runtime Patch
@module-federation/bridge-react Patch
@module-federation/devtools Patch
@module-federation/dts-plugin Patch
@module-federation/esbuild Patch
@module-federation/metro Patch
@module-federation/modern-js-v3 Patch
@module-federation/modern-js Patch
@module-federation/node Patch
@module-federation/observability-plugin Patch
@module-federation/playground Patch
@module-federation/retry-plugin Patch
@module-federation/runtime-tools Patch
@module-federation/webpack-bundler-runtime Patch
@module-federation/bridge-vue3 Patch
website-new Patch
@module-federation/metro-plugin-rnc-cli Patch
@module-federation/metro-plugin-rnef Patch
@module-federation/metro-plugin-rock Patch
shared-tree-shaking-with-server-host Patch
shared-tree-shaking-with-server-provider Patch
@module-federation/rsbuild-plugin Patch
node-dynamic-remote-new-version Patch
node-dynamic-remote Patch
@module-federation/enhanced Patch
@module-federation/rspack Patch
@module-federation/inject-external-runtime-core-plugin Patch
@module-federation/rspress-plugin Patch
remote5 Patch
remote6 Patch
@module-federation/storybook-addon Patch
shared-tree-shaking-no-server-host Patch
shared-tree-shaking-no-server-provider Patch
@module-federation/sdk Patch
@module-federation/managers Patch
@module-federation/manifest Patch
@module-federation/third-party-dts-extractor Patch
@module-federation/bridge-shared Patch
@module-federation/bridge-react-webpack-plugin Patch
@module-federation/error-codes Patch
create-module-federation Patch
@module-federation/cli Patch
@module-federation/treeshake-server Patch
@module-federation/treeshake-frontend Patch
@module-federation/utilities 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

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.

runtime-core: loadShare fails after dynamic registerShared()

1 participant