Fronts 2.0
Core concepts

Fronts 2.0 Architecture

Runtime layers, ownership boundaries, dependency direction, mount transactions, replacement, and extension points.

System boundary

Fronts turns an application reference into a governed application instance. It is deliberately split into layers so that release policy, transport, rendering framework, and execution isolation can evolve independently.

AppRef + ResolveContext


      AppResolver ───────────────► ResolvedApp<Source>


                              AppLoader selected by container
                              ├─ @fronts/mf → official MF instance
                              └─ iframe proxy → iframe agent + own MF instance


                                FrontsApp protocol

                         ┌──────────────┼──────────────┐
                         ▼              ▼              ▼
                       DOM          Shadow DOM       iframe
                         │              │              │
                         └──── scoped services + lifecycle ────┘


                         events, replacement, audit, cleanup

Dependency rule

Dependencies point inward:

  1. @fronts/core has no framework, bundler, or Module Federation dependency.
  2. @fronts/mf depends on core and peers on the public @module-federation/runtime package.
  3. @fronts/react and @fronts/vue3 depend on core and peer on their rendering framework.
  4. Examples compose packages; packages never import examples or platform policy.

No Fronts source may import @module-federation/runtime-core. The public Runtime package is the compatibility boundary. The official @module-federation/enhanced/runtime entry re-exports the same runtime through runtime-tools; a pure runtime consumer can depend directly on @module-federation/runtime, which avoids pulling in build-plugin concerns. See the audited runtime source and runtime-tools re-export.

Core abstractions

AppRef

A logical request: name, expose, optional semantic range, and optional release channel. It does not contain a CDN URL.

ResolveContext

Request policy inputs: environment, tenant, cohort, and metadata, plus an immutable host operation envelope. The host does not interpret policy fields; a resolver or registry owns selection policy. The operation envelope carries correlation and cancellation across extension boundaries.

ResolvedApp<Source>

An immutable decision containing the normalized reference, transport-specific source, selected version, and optional metadata. This object is the handoff between policy and loading. The host snapshots and freezes the decision envelope, reference, and top-level metadata. The transport source remains opaque; adapters must treat it as read-only and own any internal state.

AppLoader<Source>

A transport adapter with load() and optional preload(). A loader returns an unknown module; the host validates the Fronts application protocol before mounting it. Its context identifies the host action and includes an application identity only for mount/replace transactions.

ContainerAdapter

Prepares an execution target and owns its cleanup. A container can also select a different loader; iframe execution uses this to ensure code is loaded inside the child realm instead of the parent. The mount request may provide a static container or a resolution-aware container resolver. Planning happens before loader selection; preparation receives the resolved deployment and the correlated application operation context used for resolution and loading.

FrontsApp

The framework-neutral producer contract. React and Vue are adapters that create this contract, not special host modes.

FrontsHost

The stateful orchestrator. It resolves, loads, validates, creates a service scope, prepares a container, mounts, waits for readiness, exposes lifecycle controls, replaces instances, emits events, and audits retained resources.

Ownership compared with Module Federation 2

CapabilityMF 2Fronts
Manifest/Snapshot and asset graphOwnsConsumes as opaque runtime behavior
Remote registration and expose loadingOwnsCalls public instance methods through adapter
Shared dependency selectionOwnsDoes not intercept
Runtime loading hooks and pluginsOwnsMay correlate at its boundary
Remote type generation/downloadOwnsDoes not replace
Framework bridge render/destroyOfficial Bridge owns for Bridge appsOwn ABI adapters only
Logical app-to-deployment policyDoes not prescribeOwns resolver contract
Cross-transport lifecycle stateDoes not prescribeOwns
DOM/Shadow/iframe container policyDoes not prescribeOwns
Host service authorizationDoes not prescribeOwns
Ready-gated application replacementDoes not prescribeOwns
Application instance leak auditDoes not prescribeOwns

MF runtime plugins remain the right extension point for URL rewriting, manifest fetch behavior, script/link creation, shared resolution, and remote-load fallback. Fronts resolvers remain the right extension point for business deployment policy. Mixing those concerns makes both layers harder to reason about. See the official runtime plugin guide.

Host mount transaction

The host executes these phases in order:

  1. Normalize the reference and create operation, identity, and trace IDs.
  2. Resolve the deployment.
  3. Resolve a dynamic container request when configured, choose the default or container-specific loader from that request, and load the module.
  4. Validate protocol name/version and application shape.
  5. Create instance-bound services when configured, authorize declared capabilities, and create a revocable service scope.
  6. Prepare the container.
  7. Call mount() with the captured read-only props reference, scoped services, target, identity, and abort signal.
  8. Wait for the application ready promise with a deadline.
  9. Publish the instance as usable.

Failure unwinds every acquired resource in deterministic lifecycle order. The original error remains primary; cleanup errors are reported through typed Fronts errors and events.

Replacement transaction

replace(currentInstanceId, nextOptions) is intentionally not an in-place remote mutation:

  1. A hidden staging slot is created inside nextOptions.target; pass the current layout parent for an in-place visual replacement, or another target for an intentional move.
  2. The next deployment resolves, loads, mounts, and reaches ready in staging.
  3. If any phase fails, staging is destroyed and the current instance stays active.
  4. If ready succeeds, the new slot is committed, then the previous instance is unmounted.
  5. A previous cleanup failure is returned separately; it does not pretend the new application failed to become ready.

Concurrent replacement of one instance is rejected. This gives the platform a clear transaction boundary without mutating MF runtime caches behind an active application.

Extension points

  • Implement AppResolver for a deployment registry or experiment service.
  • Implement ResolutionCache for shared or persistent policy caching.
  • Use a container request resolver when registry metadata selects DOM, Shadow DOM, or a dedicated iframe origin per deployment.
  • Implement AppLoader for a non-MF transport.
  • Implement ContainerAdapter for another execution target.
  • Subscribe to HostEvent and map it to OpenTelemetry or an internal telemetry pipeline.
  • Use createServices for instance-bound capability implementations and deterministic cleanup.
  • Use capabilityPolicy for tenant, identity, or deployment-specific authorization.

Extension points are explicit objects, not process-wide globals.

Verification

  • pnpm check verifies package boundaries, public exports, types, lifecycle contracts, and test coverage across the workspace.
  • pnpm test:e2e and pnpm test:e2e:preview verify the documented composition against development servers and fresh production output.
  • packages/core/src owns the framework- and transport-neutral runtime.
  • packages/mf/src demonstrates the transport adapter boundary over the official Module Federation Runtime API.

On this page