Angular’s powerful router makes building single page applications seamless, but once your application grows, optimizing routes becomes vital for performance and maintainability. In this article, we’ll delve into intermediate and advanced Angular routing concepts: lazy loading modules, using route guards to protect routes, and leveraging resolvers to fetch data before navigation.
Why Lazy Loading?
As Angular applications scale, the bundle size increases, which affects initial load speed. Lazy loading allows us to load feature modules only when needed. This reduces the initial bundle size and speeds up the application startup.
Setting Up Lazy Loading
Suppose we have a feature module AdminModule
. To lazy load it, our app routing looks like:
const routes: Routes = [
{ path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) }
];
When users navigate to /admin
, Angular fetches the module on demand.
Adding Route Guards
Sensitive routes like /admin
may require authentication. We use route guards such as CanActivate
to protect them:
auth.guard.ts
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
this.router.navigate(['/login']);
return false;
}
}
Then, in your module’s routing:
{
path: '',
component: AdminComponent,
canActivate: [AuthGuard]
}
Data Pre-Fetching with Resolvers
Sometimes you want to ensure data is available before route activation. This is where resolvers shine.
admin.resolver.ts
@Injectable({ providedIn: 'root' })
export class AdminResolver implements Resolve<AdminData> {
constructor(private adminService: AdminService) {}
resolve(route: ActivatedRouteSnapshot): Observable<AdminData> {
return this.adminService.getAdminData();
}
}
Apply it to your routes:
{
path: '',
component: AdminComponent,
resolve: { adminData: AdminResolver },
canActivate: [AuthGuard]
}
Now, AdminComponent
receives the resolved data:
constructor(private route: ActivatedRoute) {
this.route.data.subscribe(data => {
this.adminData = data['adminData'];
});
}
Key Takeaways
- Lazy loading optimizes performance by loading modules on demand.
- Route guards enhance security by controlling access to routes.
- Resolvers fetch and supply route data before rendering, ensuring a smoother user experience.
Mastering these Angular routing features leads to more efficient, secure, and user-friendly applications.