Skip to content

fix: preserve default-scope shared cache aliases#862

Merged
gioboa merged 5 commits into
module-federation:mainfrom
dmchoi77:fix/default-share-cache-compat
Jun 26, 2026
Merged

fix: preserve default-scope shared cache aliases#862
gioboa merged 5 commits into
module-federation:mainfrom
dmchoi77:fix/default-share-cache-compat

Conversation

@dmchoi77

@dmchoi77 dmchoi77 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Close #858
Follow-up to #861

Summary

This adds a shared cache compatibility layer for default share-scope modules.

#861 fixes the dev optimizeDeps gate for shared singleton React, but the repro in #858 can still fail when generated runtime code looks for the same shared module under different cache keys. Newer scoped cache keys use values such as default:react, while default-scope compatibility paths can still observe the older unscoped shape, such as react.

This patch centralizes that behavior with a canonical shared cache descriptor plus default-scope aliases.

Problem

Shared dependency configuration and runtime shared cache storage are separate layers.

For example:

shared: {
  react: { singleton: true, import: false },
}

At runtime, generated loadShare wrappers and remoteEntry code store resolved shared modules in globalThis.__mf_module_cache__.share.

The same default-scope shared module may be addressed as:

default:react  # canonical scoped key
react          # default-scope compatibility alias

If one generated path writes default:react while another path reads react, the remote can miss the host-provided singleton and fall back to its own React instance. That can still produce duplicate React symptoms even after React is excluded from dev pre-bundling.

Changes

  • Added getSharedCacheDescriptor() in src/utils/packageUtils.ts.

    • canonical is the scoped cache key, for example default:react.
    • aliases contains default-scope compatibility keys, for example react.
    • Custom share scopes do not get default-scope aliases, preserving scope isolation.
  • Added generated runtime helpers:

    • __mfGetSharedCacheDescriptor
    • __mfReadSharedCache
    • __mfWriteSharedCache
  • Updated generated loadShare modules to read and write through the shared cache helpers.

  • Updated generated remoteEntry and host auto-init code to use the same helpers for:

    • external shared provider bridging,
    • singleton cache aliasing,
    • direct shared cache seeding,
    • import: false shared provider seeding,
    • host auto-init shared preloading.
  • Updated the react/compiler-runtime pre-build path to resolve React through the same compatible shared cache read.

Tests

  • Added src/utils/__tests__/packageUtils.test.ts coverage for:

    • default-scope canonical keys and aliases,
    • custom scope isolation,
    • alias read promotion to the canonical key,
    • writes to canonical and default-scope alias keys.
  • Updated virtual module tests to assert shared cache helper usage in generated loadShare, remoteEntry, and host auto-init code.

  • Updated integration coverage to verify generated shared chunks use the compatibility helpers and default-scope descriptors.

Verification

pnpm exec tsc -p tsconfig.json --noEmit
pnpm exec vitest run --dir src
pnpm exec vitest run integration
git diff --check

Results:

  • TypeScript check passed.
  • Source tests passed: 34 files / 569 tests.
  • Integration tests passed: 9 files / 34 tests.
  • Diff whitespace check passed.

pnpm exec vitest run --dir src still prints the existing MaxListenersExceededWarning, but all tests pass.

Compatibility Notes

This intentionally keeps default-scope compatibility while preserving custom-scope isolation.

New generated code reads the canonical key first. If only a default-scope alias exists, the helper promotes that value to the canonical key. Writes always store the canonical key and also fill empty alias slots for default-scope compatibility.

This should allow version-skewed host and remote builds to share the same singleton module while avoiding cross-scope collisions.

@pkg-pr-new

pkg-pr-new Bot commented Jun 26, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@module-federation/vite@862

commit: df18257

@gioboa

gioboa commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

@abhayzmp is this pre-release working for you?

@abhayzmp

Copy link
Copy Markdown

I work in IST hours and I'm packed up for the day. But feel free to just clone the repro and follow readme.md to test the changes. Once I login tomorrow I can test and revert

@gioboa gioboa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@dmchoi77 I tested the @abhayzmp 's repo an the issue is not solved.

@gioboa gioboa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tests With Different Frameworks

Image

@gioboa gioboa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I tested the repo with the issue and now it's working.
Thanks @dmchoi77 for your help 👏

@gioboa gioboa merged commit 831cf55 into module-federation:main Jun 26, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

React duplicate instance in dev mode: regression in 1.16.5, 1.16.9, 1.16.10 — 1.16.6 is the only working version

3 participants