-
Notifications
You must be signed in to change notification settings - Fork 0
Description
When using loadRemoteModule() in Angular routing (loadChildren / loadComponent), the entire navigation is blocked until the remote's remoteEntry.json and subsequent ES modules are fetched and evaluated.
Currently, this loading process happens outside Angular's Router lifecycle and Zone, making it impossible to reliably show a loading indicator (spinner/skeleton/shimmer) while the remote microfrontend is being fetched.
A lifecycle hook or observable event system would allow host applications to display proper loading states during remote module resolution.
Problem
When using loadRemoteModule() inside Angular router configuration:
{
path: 'mfe',
loadChildren: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'https://remote.app/remoteEntry.json',
exposedModule: './Module'
}).then(m => m.RemoteModule)
}Navigation fully blocks until:
remoteEntry.jsonis fetched- Remote container is initialized
- All required chunks are loaded via native
import()
During this period:
- The host shell component does not render
- No Angular router events correspond to this loading phase
- Native
import()calls cannot be intercepted - There is no place to render a loading UI
As a result, users experience blank screen delays during MFE loading.
What We Tried
1. Router Events
router.events.subscribe(...)Events like:
NavigationStartNavigationEnd
do not correlate with actual MFE loading time, since the router waits internally for loadChildren() to resolve.
2. Patching window.fetch
const originalFetch = window.fetch;
window.fetch = (...args) => {
if (args[0].includes('remoteEntry')) {
showLoading();
}
return originalFetch(...args);
};Problem:
- Only captures
remoteEntry.json - The slowest part is the subsequent
import()calls - Native
import()cannot be intercepted
Core Issue
The host shell component does not render until loadChildren() resolves.
Since the remote module loading happens before Angular renders anything:
- There is no DOM available to show loading placeholders
- Even if we intercept
remoteEntry.json, Angular renders only after allimport()calls finish, making the loading state useless.
Proposed Feature
Provide lifecycle events for remote module loading.
Option 1 — Global Observable
import { federationEvents$ } from '@angular-architects/native-federation';
federationEvents$.subscribe(event => {
if (event.type === 'loadStart') showShimmer(event.remoteName);
if (event.type === 'loadEnd') hideShimmer(event.remoteName);
});Example event payload:
type FederationEvent =
| { type: 'loadStart'; remoteName: string; exposedModule: string }
| { type: 'loadEnd'; remoteName: string; exposedModule: string }
| { type: 'loadError'; remoteName: string; error: unknown };Option 2 — Hook inside loadRemoteModule
loadRemoteModule({
remoteEntry,
exposedModule,
onLoadStart: () => showLoader(),
onLoadEnd: () => hideLoader()
});Option 3 — Angular Router Integration
Expose a router-compatible event:
RouterEvent: RemoteModuleLoadStart
RouterEvent: RemoteModuleLoadEndSimilar to Angular's:
RouteConfigLoadStartRouteConfigLoadEnd
Expected Benefits
This feature would allow:
- Showing spinners/skeletons/shimmer placeholders
- Performance tracking of remote loading
- Error handling for remote module failures
- Better UX when loading microfrontends
Environment
Angular: 21
Native Federation: latest
Usage: loadRemoteModule() with loadChildren and loadComponent
If useful, I can also provide a reproduction repository demonstrating the issue.