Hoisted Federation Runtime - Internal Technical Documentation
The hoist-container-references
branch implements a new federation runtime system with:
67% bundle size reduction for multi-entry applications (210kb → 70kb)
Runtime initialization error fixes via startup wrapper pattern
Federation dependency hoisting to runtime chunks with async exclusion
Hook-based plugin coordination system
graph TB
subgraph "Master Orchestrator"
MFRP[ModuleFederationRuntimePlugin Auto-applies other plugins]
end
subgraph "Federation Plugin System"
FMP[FederationModulesPlugin Hook Coordinator]
EFRP[EmbedFederationRuntimePlugin Startup Manager]
HCRP[HoistContainerReferencesPlugin Module Optimizer]
end
subgraph "Runtime Components"
EFRM[EmbedFederationRuntimeModule Startup Wrapper]
FRD[FederationRuntimeDependency Dependency Tracker]
end
subgraph "Compilation Hooks"
CCE[AddContainerEntryDependencyHook]
CFR[AddFederationRuntimeDependencyHook]
CRD[AddRemoteDependencyHook]
end
subgraph "Hook Publishers"
CP[ContainerPlugin during make]
RM[RemoteModule during build]
end
MFRP --> EFRP
MFRP --> HCRP
MFRP --> CFR
FMP --> CCE
FMP --> CFR
FMP --> CRD
HCRP --> CCE
HCRP --> CFR
HCRP --> CRD
EFRP --> CFR
EFRP --> EFRM
EFRP --> FRD
CP --> CCE
MFRP --> CFR
RM --> CRD
EFRM --> RuntimeStartup[__webpack_require__.startup]
Loading
1. EmbedFederationRuntimeModule (embed_federation_runtime_module.rs
)
New runtime module implementing prevStartup wrapper pattern:
#[ impl_runtime_module]
#[ derive( Debug ) ]
pub struct EmbedFederationRuntimeModule {
id : Identifier ,
chunk : Option < ChunkUkey > ,
options : EmbedFederationRuntimeModuleOptions ,
}
impl EmbedFederationRuntimeModule {
async fn generate ( & self , compilation : & Compilation ) -> Result < String > {
// Collect federation runtime dependencies in this chunk
let federation_runtime_modules = self . collect_runtime_modules ( compilation) ;
// Generate prevStartup wrapper pattern
let startup = RuntimeGlobals :: STARTUP . name ( ) ;
format ! ( r#"
var prevStartup = {startup};
var hasRun = false;
{startup} = function() {{
if (!hasRun) {{
hasRun = true;
{module_executions}
}}
if (typeof prevStartup === 'function') {{
return prevStartup();
}} else {{
console.warn('[MF] Invalid prevStartup');
}}
}};
"# )
}
}
How it works:
Stage-11 Execution : Runs after RemoteRuntimeModule
(stage 10) to get the order right
Dependency Snapshotting : Captures federation dependencies when injecting
Chunk-Aware Processing : Only handles dependencies that are actually in the chunk
Error Prevention : Checks prevStartup
before calling it and logs errors
Run-Once Logic : hasRun
flag prevents running federation initialization twice
Runtime Flow:
sequenceDiagram
participant RS as Runtime Startup
participant ESW as EmbedStartupWrapper
participant DC as Dependency Check
participant FD as Federation Dependencies
participant PS as Previous Startup
RS->>ESW: __webpack_require__.startup()
ESW->>DC: Check collected_dependency_ids
DC->>DC: has_federation_deps = !collected_deps.is_empty()
alt has_federation_deps == false
DC->>RS: return - Early exit optimization
else has_federation_deps == true
ESW->>ESW: Check hasRun flag
alt hasRun == false
ESW->>FD: Execute federation modules
ESW->>ESW: Set hasRun = true
end
ESW->>PS: Call prevStartup()
PS-->>RS: Return result
end
Loading
2. EmbedFederationRuntimePlugin (embed_federation_runtime_plugin.rs
)
Manages runtime module injection and figures out what kind of chunk we're dealing with:
#[ plugin]
pub struct EmbedFederationRuntimePlugin {
collected_dependency_ids : Arc < Mutex < FxHashSet < DependencyId > > > ,
}
impl EmbedFederationRuntimePlugin {
// Chunk Classification Strategy
async fn additional_chunk_runtime_requirements_tree ( & self , chunk_ukey : & ChunkUkey ) {
let has_runtime = chunk. has_runtime ( & compilation. chunk_group_by_ukey ) ;
let has_entry_modules = compilation. chunk_graph . get_number_of_entry_modules ( chunk_ukey) > 0 ;
// Federation support for runtime OR entry chunks
let is_enabled = has_runtime || has_entry_modules;
if is_enabled {
runtime_requirements. insert ( RuntimeGlobals :: STARTUP ) ;
}
}
// Runtime Module Injection (runtime chunks only)
async fn runtime_requirement_in_tree ( & self , chunk_ukey : & ChunkUkey ) {
if chunk. has_runtime ( & compilation. chunk_group_by_ukey ) {
let snapshot = self . collected_dependency_ids . lock ( ) . unwrap ( ) . clone ( ) ;
compilation. add_runtime_module ( chunk_ukey,
Box :: new ( EmbedFederationRuntimeModule :: new ( snapshot) ) ) ?;
}
}
}
How chunks are handled:
flowchart TD
C[Chunk Analysis] --> BTC{Is Build Time Chunk?}
BTC -->|Yes| SKIP[Skip Processing - Build chunks excluded]
BTC -->|No| RT{Has Runtime?}
C --> EM{Has Entry Modules?}
RT -->|Yes| RTC[Runtime Chunk]
RT -->|No| EM
EM -->|Yes| EC[Entry Chunk]
EM -->|No| NC[Normal Chunk]
RTC --> IRM[Inject Runtime Module]
RTC --> ARS[Add STARTUP Requirement]
EC --> ARS2[Add STARTUP Requirement]
EC --> ASC[Add Startup Call via render_startup]
NC --> Skip[Skip Processing]
IRM --> ESW[EmbedFederationRuntimeModule with Startup Wrapper]
ASC --> ESC[Explicit startup call]
Loading
Plugin Integration Points:
CompilationAdditionalChunkRuntimeRequirements
: Adds STARTUP
requirements
CompilationRuntimeRequirementInTree
: Injects runtime modules with dependency snapshots
JavascriptModulesRenderStartup
: Patches entry chunks with explicit startup calls
Hook Subscription : Registers with FederationModulesPlugin
for dependency tracking
3. HoistContainerReferencesPlugin (hoist_container_references_plugin.rs
)
Implements module hoisting that excludes async dependencies:
#[ plugin]
pub struct HoistContainerReferencesPlugin {
federation_deps : Arc < Mutex < FxHashSet < DependencyId > > > ,
}
impl HoistContainerReferencesPlugin {
// BFS Module Collection with Async Filtering
fn get_all_referenced_modules ( module : & dyn Module , ty : & str ) -> FxHashSet < ModuleIdentifier > {
let mut stack = VecDeque :: new ( ) ;
let mut visited = FxHashSet :: default ( ) ;
while let Some ( current_id) = stack. pop_front ( ) {
for conn in module_graph. get_outgoing_connections ( & current_id) {
// Critical: Exclude async block dependencies for 'initial' type
if ty == "initial" {
let parent_block = module_graph. get_parent_block ( & conn. dependency_id ) ;
if parent_block. is_some ( ) {
continue ; // Skip async dependencies
}
}
// Add to collection and continue traversal
stack. push_back ( conn. module_identifier ( ) ) ;
}
}
}
// Enhanced Runtime Chunk Detection
fn get_runtime_chunks ( compilation : & Compilation ) -> FxHashSet < ChunkUkey > {
let mut runtime_chunks = FxHashSet :: default ( ) ;
// Method 1: From entrypoints
for entrypoint in compilation. entrypoints . values ( ) {
runtime_chunks. insert ( entrypoint. get_runtime_chunk ( ) ) ;
}
// Method 2: Direct chunk runtime detection (supports runtimeChunk: 'single')
for ( chunk_ukey, chunk) in compilation. chunk_by_ukey . iter ( ) {
if chunk. has_runtime ( & compilation. chunk_group_by_ukey ) {
runtime_chunks. insert ( * chunk_ukey) ;
}
}
}
}
Three types of dependencies:
graph LR
subgraph "Federation Dependencies"
CED[Container Entry Dependencies]
FRD[Federation Runtime Dependencies]
RD[Remote Dependencies<br/>RemoteToExternal + Fallback]
end
subgraph "Collection Process"
BFS[BFS Traversal]
AF[Async Filtering]
MC[Module Collection]
end
subgraph "Hoisting Process"
RC[Runtime Chunks]
CC[Connect to Chunks]
CU[Cleanup Non-Runtime]
end
CED --> BFS
FRD --> BFS
RD --> BFS
BFS --> AF
AF --> MC
MC --> RC
RC --> CC
CC --> CU
Loading
Features:
Three collectors : Separate handling for container, runtime, and remote dependencies
BFS Algorithm : Breadth-first search to find all dependencies
Async Exclusion : Filters out async block dependencies that shouldn't be hoisted
Runtime Chunk Detection : Works with different runtimeChunk
configurations
Cleanup : Removes empty chunks and updates named chunk registry
Timing : Runs at OPTIMIZE_CHUNKS_STAGE_ADVANCED + 1
to integrate properly
4. FederationModulesPlugin (federation_modules_plugin.rs
)
Provides hooks for plugins to communicate during compilation:
// Hook Definitions for Plugin Communication
define_hook ! ( AddContainerEntryDependencyHook : Series ( dependency: & ContainerEntryDependency ) ) ;
define_hook ! ( AddFederationRuntimeDependencyHook : Series ( dependency: & FederationRuntimeDependency ) ) ;
define_hook ! ( AddRemoteDependencyHook : Series ( dependency: & dyn Dependency ) ) ;
pub struct FederationModulesPluginCompilationHooks {
pub add_container_entry_dependency : Arc < TokioMutex < AddContainerEntryDependencyHookHook > > ,
pub add_federation_runtime_dependency : Arc < TokioMutex < AddFederationRuntimeDependencyHookHook > > ,
pub add_remote_dependency : Arc < TokioMutex < AddRemoteDependencyHookHook > > ,
}
// Global hook registry with compilation isolation
static FEDERATION_MODULES_PLUGIN_HOOKS_MAP : OnceLock <
Mutex < HashMap < CompilationId , Arc < FederationModulesPluginCompilationHooks > > >
> = OnceLock :: new ( ) ;
Hook system features:
Compilation Isolation : Each compilation gets its own hook instance
Type Safety : Hooks are strongly-typed for different dependency categories
Async Support : Uses TokioMutex for async hook execution
Publisher-Subscriber : Keeps plugins loosely coupled
Thread Safety : Global registry with proper synchronization
Hook Publishers and Subscribers
Hook Triggers (Publishers)
AddContainerEntryDependencyHook
Triggered by : ContainerPlugin
during CompilerMake
phase
When : Creating container entry dependencies for exposed modules
Dependency Type : ContainerEntryDependency
AddFederationRuntimeDependencyHook
Triggered by : ModuleFederationRuntimePlugin
during CompilerFinishMake
phase
When : Creating federation runtime dependencies for runtime entry
Dependency Type : FederationRuntimeDependency
AddRemoteDependencyHook
Triggered by : RemoteModule
during module build()
phase
When : Creating remote dependencies (RemoteToExternal or Fallback)
Dependency Types : RemoteToExternalDependency
, FallbackDependency
HoistContainerReferencesPlugin - Subscribes to ALL three hooks:
Collects all federation dependencies into shared set
Uses collected dependencies during optimize_chunks
phase
Hoists federation modules to runtime chunks with BFS + async filtering
EmbedFederationRuntimePlugin - Subscribes to federation runtime hook only:
Collects federation runtime dependencies
Determines which chunks need startup wrapper
Injects EmbedFederationRuntimeModule
into runtime chunks
5. FederationRuntimeDependency (federation_runtime_dependency.rs
)
Custom dependency type for tracking federation runtime:
#[ cacheable]
#[ derive( Debug , Clone ) ]
pub struct FederationRuntimeDependency {
id : DependencyId ,
request : Cow < ' static , str > ,
// ... other fields
}
impl Dependency for FederationRuntimeDependency {
fn category ( & self ) -> & DependencyCategory {
& DependencyCategory :: Esm
}
fn dependency_type ( & self ) -> & DependencyType {
& DependencyType :: EsmImport
}
}
Two-Phase Runtime Injection
sequenceDiagram
participant MFRP as ModuleFederationRuntimePlugin
participant CP as Compilation Process
participant FMP as FederationModulesPlugin
participant EFRP as EmbedFederationRuntimePlugin
participant HCRP as HoistContainerReferencesPlugin
participant EFRM as EmbedFederationRuntimeModule
Note over MFRP: Main Orchestrator
MFRP->>EFRP: apply() during setup
MFRP->>HCRP: apply() during setup
Note over CP: Phase 1: Dependency Collection
CP->>FMP: Initialize compilation hooks
CP->>HCRP: Subscribe to all federation hooks
CP->>EFRP: Subscribe to runtime dependency hook
MFRP->>FMP: Trigger add_federation_runtime_dependency in finish_make
FMP->>HCRP: add_container_entry_dependency from ContainerPlugin
FMP->>EFRP: add_federation_runtime_dependency
FMP->>HCRP: add_remote_dependency from RemoteModuleFactory
Note over CP: Phase 2: Runtime Injection
CP->>EFRP: runtime_requirement_in_tree
EFRP->>EFRP: Create dependency snapshot
EFRP->>EFRM: Inject with snapshot
EFRM->>EFRM: Generate prevStartup wrapper
Loading
Phase 1 - Collection : Federation dependencies collected via hook system during module processing
Phase 2 - Injection : Runtime modules injected with dependency snapshots during runtime_requirement_in_tree
How chunks are classified
flowchart TB
subgraph "Chunk Analysis Pipeline"
CA[Chunk Analysis]
CA --> RTD{Has Runtime?}
CA --> EMD{Has Entry Modules?}
CA --> BTD{Is Build Time?}
end
subgraph "Processing Paths"
RTD -->|Yes + Yes| RTE[Runtime + Entry<br/>Natural Startup]
RTD -->|Yes + No| RTO[Runtime Only<br/>Inject Runtime Module]
EMD -->|No + Yes| EO[Entry Only<br/>Add Startup Call]
BTD -->|Yes| SKIP[Skip Processing]
RTD -->|No| EMD
EMD -->|No| NC[Normal Chunk<br/>Skip]
end
subgraph "Actions"
RTE --> NSH[Natural Startup Handling]
RTO --> IRM[Inject EmbedFederationRuntimeModule]
EO --> ASC[Add Explicit Startup Call]
IRM --> GSW[Generate Startup Wrapper]
ASC --> DSC[Delegate to Runtime Chunk]
end
Loading
graph TD
subgraph "Dependency Processing"
FD[Federation Dependencies] --> TTC[Three-Type Classification]
TTC --> CED[Container Entry Deps]
TTC --> FRD[Federation Runtime Deps]
TTC --> RD[Remote Deps]
end
subgraph "Collection Algorithm"
CED --> BFS1[BFS Traversal]
FRD --> BFS2[BFS Traversal]
RD --> BFS3[BFS Traversal]
BFS1 --> AF1[Async Filtering]
BFS2 --> AF2[Async Filtering]
BFS3 --> AF3[Async Filtering]
end
subgraph "Hoisting Process"
AF1 --> MC[Module Collection]
AF2 --> MC
AF3 --> MC
MC --> RCR[Runtime Chunk Resolution]
RCR --> CHC[Connect to Runtime Chunks]
CHC --> CUP[Cleanup Non-Runtime Chunks]
end
subgraph "Optimization Results"
CUP --> BSO[Bundle Size Optimization]
CUP --> ECR[Empty Chunk Removal]
CUP --> NCU[Named Chunk Updates]
end
Loading
Configuration and Integration
The hoisted runtime system turns on automatically when you use Module Federation - no configuration needed:
// Zero-configuration activation
module . exports = {
plugins : [
new ModuleFederationPlugin ( {
name : 'myApp' ,
remotes : {
'remote1' : 'remote1@http://localhost:3001/remoteEntry.js'
} ,
exposes : {
'./Component' : './src/Component'
}
} )
]
} ;
What gets enabled automatically:
✅ Startup wrapper pattern injection
✅ Runtime error prevention
✅ Proper initialization order
✅ Web worker compatibility
Bundle Size Impact by Configuration:
Configuration
Before
After
Reduction
Single Entry
140kb
140kb
0%
Multiple Entries (default)
210kb
210kb
0%
Multiple Entries + runtimeChunk: 'single'
210kb
70kb
67%
Multiple Entries + runtimeChunk: true
210kb
150kb
29%
Performance Impact & Technical Benefits
Runtime Error Elimination
The system fixes federation runtime errors in these ways:
graph LR
subgraph "Error Types Eliminated"
E1[Initialization Order Error]
E2[Federation Dependencies Not Available]
E4[Double Execution Race Conditions]
end
subgraph "Solutions Applied"
S1[Startup Wrapper Pattern]
S2[Runtime Dependency Hoisting]
S4[hasRun Flag]
end
E1 --> S1
E2 --> S2
E4 --> S4
Loading
Bundle Size Optimization Metrics
Performance numbers:
Metric
Before Enhancement
After Enhancement
Improvement
Multi-Entry Federation Bundle
210kb
70kb
67% reduction
Federation Runtime Per Entry
~70kb duplicate
Shared in runtime
~70kb saved/entry
Memory Usage (Runtime)
Fragmented across chunks
Centralized
Reduced fragmentation
Initialization Time
Variable (race conditions)
Deterministic
Consistent startup
Runtime Performance Characteristics
gantt
title Federation Initialization Timeline
dateFormat X
axisFormat %s
section Before Enhancement
Entry Chunk Load :done, e1, 0, 100
Federation Init :crit, f1, 50, 150
App Modules Load :done, a1, 75, 200
Runtime Errors :active, er, 100, 120
section After Enhancement
Runtime Chunk Load :done, r2, 0, 50
Federation Init :done, f2, 10, 60
Entry Chunk Load :done, e2, 40, 100
App Modules Load :done, a2, 90, 150
Clean Startup :milestone, cs, 150, 0
Loading
Performance benefits:
Predictable startup : Federation dependencies always initialize before modules that depend on them
Single execution : hasRun
flag prevents running initialization twice
Low overhead : Small wrapper function cost vs. error handling cost
Memory efficiency : Shared federation runtime reduces memory fragmentation
Better caching : Centralized runtime chunks work better with browser caching
Supporting Infrastructure & Integration
The federation enhancement adds a hook-based communication system:
graph TB
subgraph "Hook Registry Architecture"
FMPHM[FederationModulesPlugin<br/>Hook Manager] --> GHR[Global Hook Registry<br/>CompilationId → Hooks]
GHR --> CH1[Compilation 1 Hooks]
GHR --> CH2[Compilation 2 Hooks]
GHR --> CHN[Compilation N Hooks]
end
subgraph "Hook Types"
CH1 --> ACEDH[AddContainerEntryDependencyHook]
CH1 --> AFRDH[AddFederationRuntimeDependencyHook]
CH1 --> ARDH[AddRemoteDependencyHook]
end
subgraph "Plugin Subscribers"
HCRP[HoistContainerReferencesPlugin] --> ACEDH
HCRP --> AFRDH
HCRP --> ARDH
EFRP[EmbedFederationRuntimePlugin] --> AFRDH
end
Loading
New Dependency Type System
// Specialized dependency types for federation tracking
pub struct FederationRuntimeDependency {
id : DependencyId ,
request : Cow < ' static , str > ,
category : DependencyCategory :: Esm ,
dependency_type : DependencyType :: EsmImport ,
affect_type : AffectType :: False , // Non-affecting dependency
}
// Integration with existing dependency system
impl ModuleDependency for FederationRuntimeDependency {
fn request ( & self ) -> & str { & self . request }
fn user_request ( & self ) -> & str { & self . request }
fn set_request ( & mut self , request : String ) { /* ... */ }
}
File
Lines
Purpose
embed_federation_runtime_module.rs
119
Runtime wrapper (prevStartup pattern, stage 11)
embed_federation_runtime_plugin.rs
247
Chunk classification and runtime injection
hoist_container_references_plugin.rs
320
BFS hoisting with async exclusion
federation_modules_plugin.rs
114
Hook registry for plugin coordination
federation_runtime_dependency.rs
~80
ESM dependency type for federation runtime