/Angular-Preloading-Based-OnUserRoles

Angular 19 Preloading Based On User Roles

Primary LanguageTypeScript

Angular Preloading Based On User Role

If you want Angular route preloading but only for routes allowed by a user's role (instead of preloading everything eagerly). This is a common optimization when you use PreloadAllModules, but don't want to waste bandwidth on routes a user will never access.

👍 Step 1: Create a Custom Preloading Strategy

You can extend Angular's PreloadingStrategy using CustomPreLoadingStrategy class to decide which routes should preload. Inject this CustomPreLoadingStrategy inside app.config.ts using withPreloading.

custom-preloading.ts
import { Injectable } from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { EMPTY, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class CustomPreLoadingStrategy implements PreloadingStrategy {
  private userRole = 'user';

  preload(route: Route, fn: () => Observable<any>): Observable<any> {
    if (
      route.data?.['preload'] &&
      route.data?.['roles']?.includes(this.userRole)
    ) {
      console.log(`Preloading route /${route.path} for role: ${this.userRole}`);
      return fn();
    }
    console.log(`Skipping preload for route: /${route.path}`);
    return EMPTY;
  }
}
app.config.ts
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter, withPreloading } from '@angular/router';

import { routes } from './app.routes';
import {
  provideClientHydration,
  withEventReplay,
} from '@angular/platform-browser';
import { CustomPreLoadingStrategy } from './custom-preloading';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes, withPreloading(CustomPreLoadingStrategy)),
    provideClientHydration(withEventReplay()),
  ],
};

👍 Step 2: Add Role Metadata to Routes

When defining lazy-loaded routes, specify which roles can preload them:

app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  {
    path: 'home',
    loadComponent: () =>
      import('./components/home/home.component').then((m) => m.HomeComponent),
  },

  {
    path: 'dashboard',
    loadComponent: () =>
      import('./components/dashboard/dashboard.component').then(
        (m) => m.DashboardComponent
      ),
    data: { preload: true, roles: ['admin', 'user'] },
  },
  {
    path: 'admin',
    loadComponent: () =>
      import('./components/admin/admin.component').then(
        (m) => m.AdminComponent
      ),
    data: { preload: true, roles: ['admin'] },
  },
  {
    path: 'settings',
    loadComponent: () =>
      import('./components/settings/settings.component').then(
        (m) => m.SettingsComponent
      ),
    data: { preload: false },
  },
  {
    path: '**',
    redirectTo: 'home',
    pathMatch: 'full',
  },
];

✅ Result: If a logged-in user is admin, the admin and dashboard routes preload. If the user is just user, only dashboard and home preload. Unauthorized routes won't preload, saving bandwidth.