Skip to content

Conversation

@ScriptedAlchemy
Copy link
Contributor

@ScriptedAlchemy ScriptedAlchemy commented Oct 16, 2025

Summary

  • Add experiments.asyncStartup support for Module Federation by embedding federation runtime deps and exposing a guarded async startup hook.
  • Gate non-container entrypoints on the async federation startup promise to avoid races with remote/consume initialization.
  • Keep container/remoteEntry bundles synchronous (preserve get/init exports) while still running the embedded federation runtime setup.
  • Fix hoisting of container references to the correct runtime chunk for runtimeChunk: "single"/multi-runtime.

Notes

  • No behavior change when experiments.asyncStartup is disabled.
  • Container chunks (exposes) intentionally do not block startup on the async hook; they only run the base federation runtime setup to keep the container export sync.

Tests

  • Added MF async-startup config/serial test coverage (remoteEntry export shape, runtimeChunk single, multi-entry).
  • CI: all required checks green.

Copilot AI review requested due to automatic review settings October 16, 2025 19:48
@netlify
Copy link

netlify bot commented Oct 16, 2025

Deploy Preview for rspack ready!

Name Link
🔨 Latest commit 475bab2
🔍 Latest deploy log https://app.netlify.com/projects/rspack/deploys/695dcb3c415e5600088b886d
😎 Deploy Preview https://deploy-preview-11899--rspack.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions bot added the release: feature release: feature related release(mr only) label Oct 16, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for async startup promises across different module formats and fixes duplicate exports in module federation async startup scenarios.

  • Adds async startup promise support for multiple module formats
  • Fixes duplicate export issues in module federation async startup runtime
  • Updates test snapshots to reflect webpack runtime changes

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ 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

@github-actions
Copy link
Contributor

github-actions bot commented Oct 16, 2025

📦 Binary Size-limit

Comparing 475bab2 to chore(deps): update patch crates (#12646) by renovate[bot]

❌ Size increased by 11.38KB from 47.87MB to 47.88MB (⬆️0.02%)

@codspeed-hq
Copy link

codspeed-hq bot commented Oct 16, 2025

Merging this PR will not alter performance

Summary

✅ 16 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing feature/async-startup-runtime-promise (475bab2) with main (ece0fee)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

ScriptedAlchemy and others added 20 commits October 21, 2025 14:19
ustr-fxhash is a valid transitive dependency from rspack_cacheable
that is used by the crate's dependencies. Add it to cargo-shear's
ignored list to resolve CI dependency check failure.
Prevents wrapping container/remote chunks in Promise.resolve() when mfAsyncStartup is enabled. Only host entry chunks that need async startup should be wrapped, otherwise remote module.exports becomes a promise instead of the synchronous container object that consumers expect.

Also updates API extractor output for experiments.mfAsyncStartup field.
- Update Defaults.test.js to delete deferImport and topLevelAwait from both configs
- Update runtime modules count from 12→3 in stats snapshots (correct behavior after P0 fix)
- Remove fullHash warning expectation (no longer emitted after fix)
- Delete PROPOSAL-async-federation-startup.md

All changes align with main branch expectations after properly implementing mf_async_startup.
The plugin macro system uses these structs and methods dynamically through
trait implementations, but Rust's static analysis cannot detect this usage.
Added #[allow(dead_code)] attributes to suppress false positive warnings
in CI's deny warnings mode.

Also fixed clippy warning about unnecessary reference in runtime_chunk_map.get().
The mf_async_startup field was added to the Experiments struct, so the
defaults snapshot needs to include it.
The plugin hook macros dynamically register callback functions at runtime,
which Rust's static analysis cannot detect. Using module-level #![allow(dead_code)]
is the proper solution for macro-based callback systems where code usage is
determined at runtime rather than compile-time.
Aligned test files with main branch to fix 5 test failures:
- Restored Defaults.test.js (removed extra deferImport deletion)
- Restored base.js snapshot (removed mfAsyncStartup from inline snapshot)

The mf_async_startup field is correctly configured with IGNORE comments
in defaults.ts, allowing it to exist in the codebase while being
excluded from test comparisons.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Added mfAsyncStartup: false to defaultsCases snapshot since it's now
a valid experiment default on this branch. The IGNORE mechanism only
applies to webpack alignment tests, not defaultsCases inline snapshots.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Remove debug environment variable and eprintln! logging
- Replace fragile variable name matching with robust package path matching
- Change from matching "__module_federation_bundler_runtime__" variable name
  to matching "@module-federation/webpack-bundler-runtime" package path
- This improves maintainability and reduces coupling to generated code

The package path matching is more stable as it identifies the actual
module being imported rather than relying on a specific variable naming
convention that could change.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
These CSS package.json formatting changes are unrelated to the
Module Federation async startup feature and should match main branch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Only apply async startup runtime modules when mf_async_startup
experiment is explicitly enabled. This prevents adding extra
runtime modules to non-MF builds.

Fixes test failures where stats snapshots showed 12 runtime
modules instead of 3 for regular (non-MF) builds.
@ScriptedAlchemy ScriptedAlchemy changed the title feature/async startup runtime promise feat(mf): async federation startup promise support Dec 23, 2025
@ScriptedAlchemy ScriptedAlchemy changed the title feat(mf): async federation startup promise support feat(mf): add async startup promise gating for entrypoints Dec 23, 2025
@ScriptedAlchemy ScriptedAlchemy force-pushed the feature/async-startup-runtime-promise branch from aa3a9cc to aee3ae0 Compare January 2, 2026 23:04
export interface RawModuleFederationRuntimePluginOptions {
entryRuntime?: string | undefined
experiments?: RawModuleFederationRuntimeExperimentsOptions
asyncStartup?: boolean
Copy link
Contributor

Choose a reason for hiding this comment

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

duplicate with experiments.asyncStartup?

.into(),
);
if has_expose_entry
&& runtime_requirements.contains(RuntimeGlobals::ASYNC_FEDERATION_STARTUP)
Copy link
Contributor

Choose a reason for hiding this comment

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

The mf specific logic shouldn't place at here

// In async federation startup mode, STARTUP may return a Promise even when the entry module is
// sync (because it awaits federation init). Ensure we await the startup result before reading
// export fields so module outputs like MF containers still export live functions (get/init).
if is_async || runtime_requirements.contains(RuntimeGlobals::ASYNC_FEDERATION_STARTUP) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we just reuse the is_async? If user enable the asyncStartup, then we mark the mf entry as an async module

runtime_requirements.insert(RuntimeGlobals::ON_CHUNKS_LOADED);
// When async federation startup is requested, STARTUP_ENTRYPOINT will be present and
// the MF wrapper handles startup; avoid adding ON_CHUNKS_LOADED in that case.
if !runtime_requirements.contains(RuntimeGlobals::ASYNC_FEDERATION_STARTUP) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Here is the same, I don't want the mf specific logic affects rspack_plugin_runtime and rspack_plugin_javascript

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release: feature release: feature related release(mr only)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants