Lazy Loading
Lazy Load Components (Standalone)
Section titled “Lazy Load Components (Standalone)”import { Routes } from '@angular/router';
export const routes: Routes = [ { path: '', loadComponent: () => import('./home/home.component') .then(m => m.HomeComponent) }, { path: 'about', loadComponent: () => import('./about/about.component') .then(m => m.AboutComponent) }, { path: 'users/:id', loadComponent: () => import('./user-detail/user-detail.component') .then(m => m.UserDetailComponent) }];Lazy Load Routes
Section titled “Lazy Load Routes”// Main routesexport const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'admin', loadChildren: () => import('./admin/admin.routes') .then(m => m.ADMIN_ROUTES) }, { path: 'shop', loadChildren: () => import('./shop/shop.routes') .then(m => m.SHOP_ROUTES) }];
// admin/admin.routes.tsimport { Routes } from '@angular/router';
export const ADMIN_ROUTES: Routes = [ { path: '', loadComponent: () => import('./admin-dashboard.component') .then(m => m.AdminDashboardComponent) }, { path: 'users', loadComponent: () => import('./admin-users.component') .then(m => m.AdminUsersComponent) }];Preloading Strategies
Section titled “Preloading Strategies”No Preloading (Default)
Section titled “No Preloading (Default)”import { provideRouter } from '@angular/router';
bootstrapApplication(AppComponent, { providers: [ provideRouter(routes) // No preloading ]});PreloadAllModules
Section titled “PreloadAllModules”import { provideRouter, withPreloading, PreloadAllModules } from '@angular/router';
bootstrapApplication(AppComponent, { providers: [ provideRouter( routes, withPreloading(PreloadAllModules) // Preload all lazy routes ) ]});Custom Preloading Strategy
Section titled “Custom Preloading Strategy”import { Injectable } from '@angular/core';import { PreloadingStrategy, Route } from '@angular/router';import { Observable, of, timer } from 'rxjs';import { mergeMap } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })export class CustomPreloadStrategy implements PreloadingStrategy { preload(route: Route, load: () => Observable<any>): Observable<any> { // Preload if route has data.preload = true if (route.data?.['preload']) { console.log('Preloading:', route.path); return load(); } return of(null); }}
// Usageexport const routes: Routes = [ { path: 'admin', loadChildren: () => import('./admin/admin.routes'), data: { preload: true } // Will preload }, { path: 'shop', loadChildren: () => import('./shop/shop.routes') // Won't preload }];
bootstrapApplication(AppComponent, { providers: [ provideRouter( routes, withPreloading(CustomPreloadStrategy) ) ]});Lazy Load with Guards
Section titled “Lazy Load with Guards”export const routes: Routes = [ { path: 'admin', canActivate: [authGuard], loadChildren: () => import('./admin/admin.routes') .then(m => m.ADMIN_ROUTES) }];Bundle Analysis
Section titled “Bundle Analysis”# Build and analyze bundlesng build --stats-jsonnpx webpack-bundle-analyzer dist/your-app/stats.jsonNamed Chunks
Section titled “Named Chunks”// Webpack will create named chunks{ path: 'admin', loadChildren: () => import( /* webpackChunkName: "admin" */ './admin/admin.routes' ).then(m => m.ADMIN_ROUTES)}Lazy Load Services
Section titled “Lazy Load Services”// Service only loaded with lazy route@Injectable()export class AdminService { // ...}
// Provide in lazy routeexport const ADMIN_ROUTES: Routes = [ { path: '', component: AdminComponent, providers: [AdminService] // Only loaded with this route }];Testing Lazy Loading
Section titled “Testing Lazy Loading”describe('Lazy Loading', () => { it('should lazy load admin module', async () => { const router = TestBed.inject(Router); const fixture = TestBed.createComponent(AppComponent);
await router.navigate(['/admin']); fixture.detectChanges();
const compiled = fixture.nativeElement; expect(compiled.querySelector('app-admin')).toBeTruthy(); });});Best Practices
Section titled “Best Practices”- Lazy load feature routes (not core functionality)
- Use
PreloadAllModulesfor better UX on fast connections - Create custom strategies for conditional preloading
- Lazy load admin/dashboard routes
- Keep core features eagerly loaded
- Use bundle analysis to optimize
- Preload based on user behavior or route priority
- Group related components into route modules
- Test lazy routes to ensure they work
Performance Tips
Section titled “Performance Tips”// ✅ Good: Separate features{ path: 'admin', loadChildren: () => import('./admin/admin.routes')}
// ❌ Bad: Too granular{ path: 'user', loadComponent: () => import('./user.component') // Too small}
// ✅ Good: Group related components{ path: 'dashboard', loadChildren: () => import('./dashboard/dashboard.routes') // dashboard.routes contains multiple related components}Monitor Load Performance
Section titled “Monitor Load Performance”@Injectable({ providedIn: 'root' })export class LoadTimePreloadStrategy implements PreloadingStrategy { preload(route: Route, load: () => Observable<any>): Observable<any> { if (route.data?.['preload']) { const start = performance.now();
return load().pipe( tap(() => { const end = performance.now(); console.log(`Loaded ${route.path} in ${end - start}ms`); }) ); } return of(null); }}
