Routing
Priority: P0 (CRITICAL)
Principles
- Lazy Loading: All feature routes MUST be Lazy load all features with loadComponent (standalone) or loadChildren (route file).
- Example:
{ path: 'dashboard', loadComponent: () => import('./features/dashboard/dashboard.component').then(m => m.DashboardComponent) }.
- Example:
- Functional Guards: Use function-based guards (CanActivateFn) instead of class-based guards (guards are deprecated).
- Example:
export const authGuard: CanActivateFn = () => inject(AuthService).isAuthenticated() ? true : inject(Router).createUrlTree(['/login']). Register in routes:{ canActivate: [authGuard] }.
- Example:
- Component Inputs: Enable withComponentInputBinding() in provideRouter(routes, withComponentInputBinding()) to define input.required() in components. Angular auto-maps route params, query params, and resolve data to matching inputs.
Guidelines
- Title Strategy: Provide a custom TitleStrategy service (extending
TitleStrategyand overriding updateTitle(snapshot)) or use simple title: 'Dashboard' in route data. - Resolvers: Create a ResolveFn (e.g., inject(UserService).getUser(route.paramMap.get('id'))) to pre-fetch critical data before navigation completes (resolve: { user: userResolver }). Avoid blocking UI too long.
Anti-Patterns
- No logic in route config: no logic inside route config. Move guards for access control and data fetching to dedicated Guards and Resolvers.
- No eager feature imports: Use
loadComponentorloadChildrenfor all feature routes.
References
- Routing Patterns