fix: seed subpath shares before their package root#892
Open
YurySolovyov wants to merge 3 commits into
Open
Conversation
Since the runtime shared cache seeding (module-federation#883), serve-mode share proxies no longer bind an eager local fallback: on a cache miss they defer export assignment until after federation init. The seed loop iterated usedShared in insertion (alphabetical) order, so seeding a package root evaluated its module graph while the package's own subpath shares were still unseeded — a self-referencing bare import like `import { builder } from 'pkg/api'` inside `pkg` then read undefined named exports at module-evaluation time and crashed consumers (same failure family as module-federation#767 and module-federation#805, now in dev serve). Seed shares in dependency order instead, treating a package's subpath share keys as dependencies of the package root, with a runtime fallback for share keys discovered after codegen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
Regression in 1.16.14 (works in 1.16.13), dev serve only. When a symlinked (
file:/workspace) package is shared as a singleton together with one of its exact-key subpath exports, and the package's own source imports that subpath through a self-referencing bare specifier:the subpath share resolves with undefined named exports at module-evaluation time:
Sharing only the subpath (without the root) works;
vite buildis unaffected. This is the dev-serve reincarnation of the failure family previously fixed for production builds in #767 (fixed by #774) and #805 (fixed by #807).Root Cause
Two changes from #883 combine:
pendingShareLoadsuntil after federation init. Correct for cache reuse, but it makes seeding order load-bearing: any share proxy hit during seeding must already be cached.generateRuntimeSharedCacheSeedCode) iteratesObject.entries(usedShared), whose key order is alphabetical (getUsedShares().sort())."widgets"sorts before"widgets/api", so seeding the package rootawait share.get()evaluateswidgets/index.jswhilewidgets/apiis still unseeded — its proxy defers, its named exports stayundefined, and the root's top-level code crashes.The dependency-first ordering from #807 (
orderSharedDependenciesFirst) already exists but wasn't used by the new seed loop, and it didn't know that a package root implicitly depends on its own subpath shares.Fix
orderSharedDependenciesFirstnow treats a package's subpath share keys as dependencies of the package root: when visiting a root key, its subpath keys are visited (and therefore ordered) first. Subpath keys also resolve their dependency list through the root package'spackage.jsonwhen the subpath itself doesn't resolve to one.generateRuntimeSharedCacheSeedCodeseeds ingetOrderedUsedShares()order (embedded at codegen time) instead ofusedSharedinsertion order, with a runtime fallback that appends any share keys discovered after codegen so nothing is skipped.This preserves #883's cache-reuse semantics — no eager fallback is reintroduced; the fix only makes the seeding order match the evaluation-order requirements the deferred fallback created. For the example above the seed order becomes
['widgets/api', 'widgets'], so by the timewidgets/index.jsevaluates, thewidgets/apiproxy hits a warm cache and applies its exports synchronously.Known limitation: a genuine evaluation-time cycle (root imports subpath and subpath imports root) cannot be solved by ordering alone; that case was equally broken before this change.