13
Module 13: Optimize Angular Micro Frontends with Shared Dependencies
Chapter 13 • Advanced
35 min
Optimize Angular Micro Frontends with Shared Dependencies
You will learn:
- How to share Angular core libraries
- How to avoid duplicate bundles
- How to reduce initial load time
- How to prevent version conflicts
This is critical for production systems.
The Problem: Duplicate Bundles
Without Sharing
code
Host App Bundle: 2.5 MB (includes Angular core)
Products App Bundle: 2.3 MB (includes Angular core)
Checkout App Bundle: 2.4 MB (includes Angular core)
Total: 7.2 MB (duplicate Angular core)
With Sharing
code
Host App Bundle: 2.5 MB (includes Angular core)
Products App Bundle: 0.8 MB (no Angular core)
Checkout App Bundle: 0.9 MB (no Angular core)
Total: 4.2 MB (Angular core loaded once)
Savings: 3 MB (42% reduction)
Shared Dependencies Strategy
What to Share
- ✅ Angular core libraries (
@angular/core,@angular/common, etc.) - ✅ RxJS (used everywhere)
- ✅ Common utilities
- ✅ Shared UI libraries
What NOT to Share
- ❌ Domain-specific libraries
- ❌ Large third-party libraries (unless needed)
- ❌ App-specific code
Configuration for Performance
Optimal Shared Config
typescript.js
shared: {
'@angular/core': {
singleton: true,
strictVersion: true,
requiredVersion: '^15.0.0',
eager: false // Lazy load (default)
},
'@angular/common': {
singleton: true,
strictVersion: true,
requiredVersion: '^15.0.0',
eager: false
},
'@angular/router': {
singleton: true,
strictVersion: true,
requiredVersion: '^15.0.0',
eager: false
},
'rxjs': {
singleton: true,
strictVersion: true,
requiredVersion: '^7.0.0',
eager: false
}
}
Bundle Size Analysis
Analyze Bundle Sizes
bash.js
# Build for production
npx ng build --configuration production
# Analyze bundles
npx webpack-bundle-analyzer dist/host-app/stats.json
What to Look For
- ✅ Angular core loaded once
- ✅ No duplicate libraries
- ✅ Reasonable bundle sizes
- ✅ Lazy loading working
Lazy Loading Strategy
Route-Based Lazy Loading
typescript.js
const routes: Routes = [
{
path: 'products',
loadChildren: () => import('products/ProductsModule')
.then(m => m.ProductsModule) // Loaded on demand
}
]
Benefits:
- ✅ Initial bundle smaller
- ✅ Load modules on demand
- ✅ Better performance
Preloading Strategy
Preload All Modules
typescript.js
import { PreloadAllModules } from '@angular/router'
RouterModule.forRoot(routes, {
preloadingStrategy: PreloadAllModules
})
Custom Preloading
typescript.js
import { PreloadingStrategy, Route } from '@angular/router'
import { Observable, of } from 'rxjs'
export class CustomPreloadStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any> {
if (route.data && route.data['preload']) {
return load()
}
return of(null)
}
}
Code Splitting
Automatic Code Splitting
Module Federation automatically splits:
- ✅ Each remote app
- ✅ Shared dependencies
- ✅ Route-based chunks
Manual Code Splitting
typescript.js
// Lazy load a component
const LazyComponent = () => import('./lazy.component')
.then(m => m.LazyComponent)
Caching Strategy
Cache remoteEntry.js
typescript.js
// Use versioned URLs
remotes: {
products: 'products@https://products.example.com/v1.2.3/remoteEntry.js'
}
Cache Shared Dependencies
- ✅ Use CDN for shared libraries
- ✅ Version shared dependencies
- ✅ Long cache headers
Performance Metrics
Key Metrics
- Initial Load Time: Time to first paint
- Time to Interactive: When app becomes usable
- Bundle Size: Total JavaScript size
- Network Requests: Number of HTTP requests
Target Metrics
- ✅ Initial load < 3 seconds
- ✅ Time to interactive < 5 seconds
- ✅ Bundle size < 2 MB (gzipped)
- ✅ Network requests < 20
Optimization Techniques
1. Tree Shaking
typescript.js
// Only import what you need
import { Component } from '@angular/core' // ✅ Good
import * as Angular from '@angular/core' // ❌ Bad
2. Lazy Loading
typescript.js
// Load on demand
loadChildren: () => import('./module') // ✅ Good
import { Module } from './module' // ❌ Bad
3. Code Splitting
typescript.js
// Split large features
const LargeFeature = () => import('./large-feature') // ✅ Good
Monitoring Performance
Web Vitals
typescript.js
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'
getCLS(console.log)
getFID(console.log)
getFCP(console.log)
getLCP(console.log)
getTTFB(console.log)
Bundle Analysis
bash.js
# Install analyzer
npm install --save-dev webpack-bundle-analyzer
# Analyze
npx webpack-bundle-analyzer dist/stats.json
Common Performance Issues
Issue 1: Duplicate Dependencies
Problem: Same library loaded multiple times
Solution: Add to shared config
Issue 2: Large Initial Bundle
Problem: Everything loaded upfront
Solution: Use lazy loading
Issue 3: Slow Remote Loading
Problem: Network latency
Solution: Use CDN, enable caching
Best Practices
✅ Do
- Share Angular core libraries
- Use lazy loading
- Monitor bundle sizes
- Optimize shared dependencies
- Use CDN for shared libraries
❌ Don't
- Don't share everything
- Don't load everything upfront
- Don't ignore bundle sizes
- Don't skip performance monitoring
Next Steps
Performance optimization complete!
Next module: Routing between micro frontends.