feat(runtime): support auth headers and additional fetch options when loading remote modules#4827
feat(runtime): support auth headers and additional fetch options when loading remote modules#4827smeng9 wants to merge 34 commits into
Conversation
🦋 Changeset detectedLatest commit: 6061b9b The changes in this PR will be included in the next version bump. This PR includes changesets to release 47 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 |
✅ Deploy Preview for module-federation-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3686009e9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
00527f7 to
9195060
Compare
|
The ESM loading direction makes sense, but I don't think The runtime already has a This also avoids expanding the public remote config API. Users can already decide headers based on So I think the change should keep remote registration unchanged, and make ESM remote entry / related ESM asset loading go through the existing |
|
Hi @2heal1 I have applied your suggestions to keep the function signature the same for registerRemotes. Would you mind take another look? Thanks! |
@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/retry-plugin
@module-federation/rsbuild-plugin
@module-federation/rspack
@module-federation/rspress-plugin
@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 Report18 package(s) changed, 23 unchanged. Package dist + ESM entry
Bundle targets
Consumer scenarios
Total dist (raw): 6.85 MB (+32.6 kB (+0.5%)) Bundle sizes are generated with rslib (Rspack). Package-root metrics preserve the historical report. Tracked subpath exports such as |
|
Hi @2heal1 I have rebased my tests to use newly merged rstest |
Design for threading per-remote fetchOptions through registerRemotes so auth/compliance headers reach every asset in the ESM module graph (manifest, entry, chunks, shared deps, manifest CSS) via a fetch + blob import-rewriting loader. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…motes Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
… loading Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Distinguishes the JS module blob cache from cssCache. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
dom.iterable surfaces Headers.entries()/Symbol.iterator on the standard DOM types, so toHeaderObject can use Object.fromEntries(headers.entries()) without the unknown-cast workaround. Verified: all 42 packages build, sdk type-checks, sdk tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Call-level fetchOptions now act as defaults that each remote's own fetchOptions are merged on top of (remote wins on conflict), with headers merged per-key so a remote adding one header no longer drops the call-level ones. Exposes toHeaderObject from sdk to share the header-normalization used by the merge. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The entry preload in preloadAssets used the snapshot-derived moduleInfo, which does not carry the host remote's fetchOptions. The remoteEntry was therefore preloaded unauthenticated and cached, so the later authenticated load was skipped and no Authorization header reached the remoteEntry or its chunks. Forward remoteInfo.fetchOptions to the entry preload (mirroring the css path). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…docs Document the per-remote/call-level fetchOptions option on registerRemotes in the runtime API reference (en + zh), and remove the internal superpowers plan/spec scratch files under docs/. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- runtime-core/load: wrap blob-loader ESM entry failures as RUNTIME_008 so getRemoteEntry's loadEntryError recovery (token refresh, failover) still fires for authenticated ESM remotes - runtime-core/preload: skip applying authenticated CSS during preload hints (useLinkPreload) so a remote's stylesheet no longer overrides host styles before the remote is loaded - sdk/blobLoad: store dynamic-import contexts in a shared globalThis registry and stop clobbering an existing __mfDyn shim, so blob modules keep their fetch context when two bundled copies of the SDK coexist Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Instead of adding a separate __MF_BLOB_LOAD_CONTEXTS__ global, attach the shared dynamic-import context map as a property of the single global __mfDyn shim. Avoids polluting globalThis with a second variable while keeping the cross-SDK-copy guarantee: every copy reads/writes the same map through whichever shim is installed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
getContexts() already installs the __mfDyn shim idempotently, so the only thing the flag still guarded was duplicate vite:preloadError listeners. Use a stable handler reference instead — addEventListener treats an identical (callback, capture) pair as a no-op — and remove the flag. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- __mfDyn -> __mfDynImport (global dynamic-import shim) - MFDynShim -> MFDynImportShim - getContexts -> createOrGetBlobLoaderContexts - shim.contexts -> shim.blobLoaderContexts - BlobLoadContext -> BlobLoaderContext Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Extract pushCssAsset so the three CSS branches (authenticated fetch, rel=preload hint, applied rel=stylesheet) share a single forEach instead of repeating the cssAssets.forEach/results.push boilerplate. Behavior is unchanged: needDeleteLink stays undefined for the preload hint and false for the applied stylesheet. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…registerRemotes config
Address PR review (2heal1): header/auth customization is request behavior, so
configure it through the existing `fetch` hook (which already receives
`remoteInfo`) rather than a new `fetchOptions` field on remote registration.
- Remove `fetchOptions` from `RemoteInfoCommon`/`RemoteInfo`, the
`registerRemotes` options, and the call-level merge helper; revert the
manifest fetch to its prior `{}` init (it already passed `remoteInfo`).
- Gate the ESM remote-entry and manifest-CSS blob loaders on fetch-hook
presence (`loaderHook.fetch.listeners.size > 0`) instead of `fetchOptions`,
routing their requests through the hook with `remoteInfo`/`resourceContext`.
With no fetch hook, remotes load via native import()/<link> as before.
- Rename/rewrite tests to cover the hook-presence gate; update EN/ZH docs to
document the `fetch` hook approach and refresh the changeset.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…ng behavior The test only asserted that the manifest request is emitted through the fetch hook with remoteInfo as the 3rd arg — behavior that predates this branch (it was already in place at v2.5.0) and that the test never inspected the init arg this branch actually touched. It guarded no code introduced here, so remove it. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
rs.spyOn/rs.mock on @module-federation/sdk never intercepts calls from src/utils/load.ts and preload.ts: their named imports bind directly to the sdk's inner dist modules, bypassing the mocked package entry. Follow the sdk blobLoad.spec.ts idiom instead — run the real blob loader, stub globalThis.fetch and URL.createObjectURL, and assert the observable fetch/hook-emit behavior. Co-Authored-By: Claude Fable 5 <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
6b4c56a to
6061b9b
Compare
|
Hi @2heal1 I have rebased with recent merges, including the added new language. Could you please help us to close the compliance gap? Thanks! |
Description
A compliance requirement in the backend gateway needs an Authorization: Bearer … header (plus arbitrary X-* headers) for loading remote modules. Previously all assets that are fetched with no authorization header will be rejected under new access control model.
This PR adds per-remote fetchOptions so federated ESM/module remotes can be loaded with custom HTTP headers on their manifest, remote entry, split chunks, shared deps, and CSS requests.
Related Issue
Multiple people had requested this feature before
module-federation/utilities#13
module-federation/enhanced#21
Additionally previous discussions are outdated,
they involve webpack require() instead of esm import()
#1115
Types of changes
Checklist