Repository navigation
feat(runtime): add pause/resume hooks and preserve ESM entries - #4891
zackarychapple wants to merge 3 commits into
Conversation
🦋 Changeset detectedLatest commit: c641af6 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 |
06e2d21 to
8216621
Compare
@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/playground
@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 Report13 package(s) changed, 29 unchanged. Package dist + ESM entry
Bundle targets
Consumer scenarios
Total dist (raw): 35.71 MB (+12.9 kB (+0.0%)) Bundle sizes are generated with rslib (Rspack). Package-root metrics preserve the historical report. Tracked subpath exports such as |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c641af636f
ℹ️ 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 "@codex address that feedback".
| export interface ResumeCommittedEvent extends ApplicationLifecycleTransition { | ||
| committedAt: number; | ||
| } |
There was a problem hiding this comment.
Preserve checkpoint on committed resumes
When a host resumes from a checkpoint, preResume exposes checkpointReference, but the committed resume event drops it here. Plugins that only react after a successful resume cannot tell which checkpoint was activated without keeping separate state or casting around the public type, so the new lifecycle API loses the checkpoint metadata on the completion event.
Useful? React with 👍 / 👎.
Nsttt
left a comment
There was a problem hiding this comment.
A few lifecycle contract questions from a local pass. The ESM metadata change looks good to me; these are the pieces in the new hook group that still feel risky.
| >(), | ||
| }); | ||
| applicationHook = new PluginSystem({ | ||
| prePause: new AsyncHook< |
There was a problem hiding this comment.
Could we define aggregation here instead of inheriting the AsyncHook last-result-wins behavior? With two plugins returning { delayMs: 5000 } and { delayMs: 10 }, the host only receives 10, so it cannot consider the first request. Returning all decisions, or explicitly taking the maximum, plus a multi-plugin test would make this contract predictable.
| | false | ||
| | Promise<LifecycleDecision | void | false> | ||
| >('prePause'), | ||
| pause: new AsyncHook< |
There was a problem hiding this comment.
I do not think the generic AsyncHook semantics fit these committed/error notifications. A listener can return false, or reject, which prevents every later plugin from seeing a pause or resume that already happened. Could these hooks use serial fan-out that always attempts every listener, with an explicit error policy?
| instance.snapshotHandler.hooks, | ||
| instance.loaderHook, | ||
| instance.bridgeHook, | ||
| instance.applicationHook, |
There was a problem hiding this comment.
One subtle side effect of adding another PluginSystem: every runtime plugin now goes through applyPlugin once more, and each system has its own registration map. That changes plugin.apply(instance) from six calls to seven even for plugins with no application hooks. Could apply be owned by host-level registration and run once, separately from wiring callbacks into each hook group?
|
Could you please split the ESM remote-entry metadata fix into a separate PR? That fix addresses a general manifest/runtime loading issue and is independent of the application pause/resume proposal. Keeping it separate will make the change easier to review, validate, and merge on its own. |
|
The pause/resume lifecycle model appears specific to your application platform rather than a general Module Federation runtime concern. Please implement this behavior through a custom MF RuntimePlugin instead of adding these hooks and types to You can follow the approach used in If multiple unrelated consumers later need the same lifecycle model, we can revisit whether a smaller, proven abstraction belongs in core. |
Summary
Adds runtime primitives for host-supervised application pause/resume transitions and preserves native ESM remote-entry metadata in emitted manifests.
Changes
prePause,pause,preResume,resume, andlifecycleErrorruntime-plugin hooks.@module-federation/runtime-coreand@module-federation/runtime.library.type: "module"when reconciling pre-emitted Rspack stats so generated manifests select the ESM remote-entry loader.Scope
This PR provides Federation runtime primitives only. The host remains responsible for transition serialization, deadline enforcement, cancellation/force policy, checkpoints, authorization, activation/mount/update/rollback, and installation state. Bridge render/destroy hooks remain rendering instrumentation rather than authoritative lifecycle boundaries.
Validation
pnpm --filter @module-federation/runtime-core run test -- hooks.spec.tspnpm --filter @module-federation/runtime run testpnpm --filter @module-federation/manifest run test@module-federation/runtime-core,@module-federation/runtime, and@module-federation/manifestpnpm exec prettier --checkfor the touched files