Claude
Skills
Sign in
Back

routing-performance-implementation

Included with Lifetime
$97 forever

Configure routing with lazy loading, implement route guards, set up preloading strategies, optimize change detection, analyze bundles, and implement performance optimizations.

Generalscriptsassets

What this skill does


# Routing & Performance Implementation Skill

## Quick Start

### Basic Routing
```typescript
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent, AboutComponent, NotFoundComponent } from './components';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: '**', component: NotFoundComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```

### Navigation
```typescript
import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  template: `
    <button (click)="goHome()">Home</button>
    <a routerLink="/about">About</a>
    <a routerLink="/users" [queryParams]="{ tab: 'active' }">Users</a>
  `
})
export class NavComponent {
  constructor(private router: Router) {}

  goHome() {
    this.router.navigate(['/']);
  }
}
```

### Route Parameters
```typescript
const routes: Routes = [
  { path: 'users/:id', component: UserDetailComponent },
  { path: 'users/:id/posts/:postId', component: PostDetailComponent }
];

// Component
@Component({...})
export class UserDetailComponent {
  userId!: string;

  constructor(private route: ActivatedRoute) {
    this.route.params.subscribe(params => {
      this.userId = params['id'];
    });
  }
}

// Or with snapshot
ngOnInit() {
  const id = this.route.snapshot.params['id'];
}
```

## Lazy Loading

### Feature Modules with Lazy Loading
```typescript
// app-routing.module.ts
const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'users',
    loadChildren: () => import('./users/users.module').then(m => m.UsersModule)
  },
  {
    path: 'products',
    loadChildren: () => import('./products/products.module').then(m => m.ProductsModule)
  }
];

// users/users-routing.module.ts
const routes: Routes = [
  { path: '', component: UserListComponent },
  { path: ':id', component: UserDetailComponent }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class UsersRoutingModule { }
```

### Lazy Loading with Standalone Components
```typescript
const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.routes').then(m => m.ADMIN_ROUTES)
  }
];

// admin/admin.routes.ts
export const ADMIN_ROUTES: Routes = [
  { path: '', component: AdminDashboardComponent },
  { path: 'users', component: AdminUsersComponent }
];
```

## Route Guards

### CanActivate Guard
```typescript
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
import { map } from 'rxjs/operators';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private authService: AuthService,
    private router: Router
  ) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    return this.authService.isAuthenticated$.pipe(
      map(isAuth => {
        if (isAuth) return true;
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
        return false;
      })
    );
  }
}

// Usage
const routes: Routes = [
  { path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
];
```

### CanDeactivate Guard
```typescript
export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean> | boolean;
}

@Injectable()
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
  canDeactivate(component: CanComponentDeactivate): Observable<boolean> | boolean {
    return component.canDeactivate();
  }
}

// Component
@Component({...})
export class FormComponent implements CanComponentDeactivate {
  form!: FormGroup;

  canDeactivate(): Observable<boolean> | boolean {
    return !this.form.dirty || confirm('Discard changes?');
  }
}

// Usage
{ path: 'form', component: FormComponent, canDeactivate: [CanDeactivateGuard] }
```

### Resolve Guard
```typescript
@Injectable()
export class UserResolver implements Resolve<User> {
  constructor(private userService: UserService) {}

  resolve(route: ActivatedRouteSnapshot): Observable<User> {
    return this.userService.getUser(route.params['id']);
  }
}

// Usage
{
  path: 'users/:id',
  component: UserDetailComponent,
  resolve: { user: UserResolver }
}

// Component receives data
@Component({...})
export class UserDetailComponent {
  user!: User;

  constructor(private route: ActivatedRoute) {
    this.route.data.subscribe(data => {
      this.user = data['user'];
    });
  }
}
```

## Query Parameters

```typescript
// Navigation
this.router.navigate(['/users'], {
  queryParams: {
    page: 1,
    sort: 'name',
    filter: 'active'
  }
});

// Reading
this.route.queryParams.subscribe(params => {
  const page = params['page'];
  const sort = params['sort'];
});

// Template
<a [routerLink]="['/users']" [queryParams]="{ page: 2, sort: 'name' }">
  Next Page
</a>
```

## Fragment (Hash)

```typescript
// Navigation
this.router.navigate(['/docs'], { fragment: 'section1' });

// Reading
this.route.fragment.subscribe(fragment => {
  console.log('Fragment:', fragment);
});

// Template
<a routerLink="/docs" fragment="section1">Section 1</a>
```

## Preloading Strategies

```typescript
// Default: no preloading
RouterModule.forRoot(routes);

// Preload all lazy modules
RouterModule.forRoot(routes, {
  preloadingStrategy: PreloadAllModules
});

// Custom preloading strategy
@Injectable()
export class SelectivePreloadingStrategy implements PreloadingStrategy {
  preload(route: Route, load: () => Observable<any>): Observable<any> {
    if (route.data && route.data['preload']) {
      return load();
    }
    return of(null);
  }
}

// Usage
const routes: Routes = [
  { path: 'users', loadChildren: '...', data: { preload: true } }
];

RouterModule.forRoot(routes, {
  preloadingStrategy: SelectivePreloadingStrategy
})
```

## Route Reuse Strategy

```typescript
@Injectable()
export class CustomRouteReuseStrategy implements RouteReuseStrategy {
  storedRoutes: { [key: string]: RouteData } = {};

  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return route.data['cache'] === true;
  }

  store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {
    this.storedRoutes[route.url.join('/')] = { route, handle: detachedTree };
  }

  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return !!this.storedRoutes[route.url.join('/')];
  }

  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
    return this.storedRoutes[route.url.join('/')]?.handle || null;
  }

  shouldReuseRoute(future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
    return future.routeConfig === current.routeConfig;
  }
}
```

## Performance Optimization

### Code Splitting
```typescript
// Only load admin module when needed
{
  path: 'admin',
  loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}
```

### Change Detection with Routes
```typescript
@Component({
  selector: 'app-root',
  template: `<router-outlet></router-outlet>`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent { }
```

### Scroll Position

```typescript
// Scroll to top on route change
RouterModule.forRoot(routes, {
  scrollPositionRestoration: 'top'
})

// Or custom scroll
export class ScrollToTopComponent implements OnInit {
  constructor(private router: Router) {}

  ngOnInit() {
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe(() => {
      window.scrollTo(0, 0);
    });
  }
}
```

## Advanced Patterns

### Auxiliary Routes
```typescript
// URL: /users/1(admin:admin-panel)
<router-outlet></router-outlet>
<router-outlet name="admin"></router-o

Related in General