Skip to the solution
HardFrontend7 min read

What are preloading strategies?

292 views

The problem

Question presented to candidate: "We moved every feature behind lazy routes and the first load got faster, but now opening each section for the first time has a noticeable pause. What are preloading strategies in Angular, and which one would you pick?"

What a strong answer should cover:

  • Preloading downloads lazy route code in the background after a navigation finishes, so a later navigation to that route needs no download.
  • The built-in strategies: NoPreloading (the default) and PreloadAllModules, enabled with provideRouter(routes, withPreloading(...)).
  • A custom strategy is a class implementing PreloadingStrategy.preload(route, load) that decides per route: call load() or return EMPTY.
  • Preloading covers both loadChildren and loadComponent, runs after NavigationEnd, and does not consult canMatch (routes with the deprecated canLoad are skipped).
  • The trade-off: initial load stays small, but users pay bandwidth for screens they may never open; mobile and metered connections deserve care.

Clarifying questions expected:

  • "Do most users visit most sections, or only one or two?"
  • "Are there areas, like admin, that most users should never download?"

Code / implementation expected: Yes β€” withPreloading(PreloadAllModules) and a log showing when the loaders run compared with NoPreloading.

  • routing
  • preloading

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

7 min read Β· 9 sections

Read the code

AngularPreloadAllModules with loader logs, including a canMatch-protected route
import { ApplicationConfig, Component, inject } from "@angular/core";
import {
  NavigationEnd, NavigationStart, PreloadAllModules, Router, RouterOutlet, Routes,
  provideRouter, withPreloading,
} from "@angular/router";

@Component({ selector: "app-home", template: `<p>Home</p>` })
export class HomeComponent {}
@Component({ selector: "app-settings", template: `<p>Settings (lazy)</p>` })
export class SettingsComponent {}
@Component({ selector: "app-orders", template: `<p>Orders (lazy)</p>` })
export class OrdersComponent {}
@Component({ selector: "app-admin", template: `<p>Admin (lazy)</p>` })
export class AdminComponent {}

// Stand-ins for () => import("./settings/settings") etc.
const load = <T>(name: string, value: T) => () => {
  console.log(`  loader(${name}) called`);
  return Promise.resolve(value);
};

export const routes: Routes = [
  { path: "", component: HomeComponent },
  { path: "settings", loadComponent: load("settings", SettingsComponent) },
  { path: "orders", loadChildren: load("orders", [{ path: "", component: OrdersComponent }]) },
  // canMatch says no to everyone here. Preloading downloads it anyway.
  { path: "admin", canMatch: [() => false], loadComponent: load("admin", AdminComponent) },
];

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes, withPreloading(PreloadAllModules))],
};

@Component({ selector: "app-root", imports: [RouterOutlet], template: `<router-outlet />` })
export class AppComponent {
  readonly router = inject(Router);
  constructor() {
    this.router.events.subscribe((e) => {
      if (e instanceof NavigationStart) console.log(`  NavigationStart ${e.url}`);
      if (e instanceof NavigationEnd) console.log(`  NavigationEnd   ${e.urlAfterRedirects}`);
    });
  }
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 113 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextHard

What is the critical render path and how does Angular handle font and style optimization?

Continue