Effective routing is critical in micro frontend applications to ensure seamless navigation while maintaining independence between components. Here’s a deep dive into sophisticated routing strategies:
Hierarchical Routing Architecture
1. Three-Tier Routing Model
- Shell Router: Handles top-level routes and micro frontend mounting
// Shell router configuration
const routes = [
{
path: '/ecommerce/*',
mount: () => import('ecommerce-mfe'),
metadata: { requiresAuth: true }
},
{
path: '/cms/*',
mount: () => import('cms-mfe'),
metadata: { role: 'editor' }
}
];
- Micro Frontend Router: Manages sub-routes within its domain
- Component Router: Handles internal component navigation
2. Dynamic Route Federation
- Micro frontends expose routes at runtime via a central registry:
// Route registration protocol
window.routeRegistry.register({
scope: 'products',
routes: [
{ path: '/list', component: ProductList },
{ path: '/:id', component: ProductDetail }
],
guards: [authGuard]
});
Advanced Navigation Patterns
1. Cross-MFE Navigation with State Transfer
// Navigation with state payload
shell.navigate('/checkout', {
state: {
cartItems: selectedItems,
referrer: 'product-page'
},
transition: 'slide-left'
});
2. Route Interception Middleware
// Global navigation guard
router.beforeEach((to, from, next) => {
if (to.metadata.requiresUpdate) {
showUpdateModal().then(next).catch(redirectToFallback);
} else {
next();
}
});
Framework-Specific Implementations
React with Module Federation
// Dynamic route loading
const ProductRoutes = React.lazy(() => import('productsApp/routes'));
function App() {
return (
<Routes>
<Route path="/products/*" element={
<Suspense fallback={<Spinner />}>
<ProductRoutes />
</Suspense>
}/>
</Routes>
);
}
Angular with Standalone Components
// Shell app routing
export const routes: Routes = [
{
path: 'dashboard',
loadChildren: () => loadRemoteModule({
remoteEntry: 'http://mfe1.example.com/remoteEntry.js',
remoteName: 'dashboard',
exposedModule: './Routes'
}).then(m => m.DASHBOARD_ROUTES)
}
];
Stateful Routing Solutions
1. Route-Based State Management
// Route state synchronization
window.addEventListener('popstate', (event) => {
if (event.state?.mfeState) {
store.dispatch({
type: 'ROUTE_STATE_UPDATE',
payload: event.state.mfeState
});
}
});
2. URL-Centric Data Loading
// Data fetching based on route params
const ProductPage = () => {
const { id } = useParams();
const [product, setProduct] = useState(null);
useEffect(() => {
const productData = await fetchProduct(id);
window.dispatchEvent(new CustomEvent('product-view', { detail: productData }));
}, [id]);
};
Performance Optimization
- Route-Based Code Splitting
// Dynamic import with prefetching
const Checkout = () => import(/* webpackPrefetch: true */ './Checkout');
- Intelligent Preloading
// Predictive loading based on user behavior
router.on('hover', (route) => {
if (shouldPreload(route)) {
route.preload();
}
});
Error Handling Strategies
1. Graceful Degradation
// Fallback routes
const routes = [
{
path: '/reports',
component: ReportsApp,
fallback: <LegacyReports />,
errorBoundary: <ReportsErrorView />
}
];
2. Micro Frontend Health Checks
// Route availability verification
router.beforeResolve(async (to) => {
if (to.meta.mfeHealthCheck) {
const healthy = await checkMFEHealth(to.path);
if (!healthy) throw new Error('MFE unavailable');
}
});
Emerging Patterns
1. Edge-Side Routing
- CDN-level routing decisions
- Reduced client-side routing complexity
- Improved performance through edge caching
2. AI-Driven Route Optimization
- Dynamic route prioritization based on usage patterns
- Predictive loading of likely next routes
- Adaptive route prefetching strategies
Implementation Checklist
- [ ] Establish clear route ownership boundaries
- [ ] Implement cross-MFE navigation protocol
- [ ] Set up route conflict detection system
- [ ] Configure shared navigation state management
- [ ] Develop comprehensive error handling
- [ ] Optimize route-based resource loading
- [ ] Implement analytics for route performance