Skip to the solution
MediumFrontend9 min read

How does routing and lazy loading work in Angular?

156 views

The problem

Question presented to candidate: "Our Angular app has grown to forty screens and the first load is slow. Explain how the router decides what to show for a URL, and how lazy loading would help us here."

What a strong answer should cover:

  • The router maps URL paths to components using a Routes array registered with provideRouter(routes); <router-outlet> is where the matched component renders and routerLink navigates without a page reload.
  • Matching is first match wins, in array order, with ** as a wildcard and redirectTo for redirects.
  • Lazy loading with loadComponent (one standalone component) or loadChildren (a whole set of child routes) wraps a dynamic import(), which the build turns into a separate chunk that downloads only when needed.
  • The loader runs on the first navigation to that route and is cached afterwards; the router emits RouteConfigLoadStart / RouteConfigLoadEnd around it.
  • Concrete effect on the initial bundle, and the follow-up options: preloading, guards that run before the download (canMatch), and @defer for parts of a page.

Clarifying questions expected:

  • "Are the screens standalone components already, or still grouped in NgModules?"
  • "Is the slow part the JavaScript download, or data fetching after the screen appears?"

Code / implementation expected: Yes β€” a routes array with one eager route, one loadComponent and one loadChildren route.

  • routing

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

9 min read Β· 10 sections

Read the code

AngularEager, loadComponent and loadChildren routes with loader and router-event logs
import { ApplicationConfig, Component, inject, signal } from "@angular/core";
import {
  NavigationEnd, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouterLink,
  RouterOutlet, Routes, provideRouter,
} from "@angular/router";

@Component({ selector: "app-home", template: `<p>Home page</p>` })
export class HomeComponent {}

// In a real app each lazy piece lives in its own file and the loader is
//   () => import("./admin/admin.component").then(m => m.AdminComponent)
// The bundler turns that import() into a separate chunk. Here the classes sit
// in one file so the example is self-contained; the loaders log when called.
@Component({ selector: "app-admin", template: `<p>Admin page (lazy component)</p>` })
export class AdminComponent {}

@Component({ selector: "app-orders", template: `<p>Order list (lazy child routes)</p>` })
export class OrdersComponent {}

export const routes: Routes = [
  { path: "", component: HomeComponent },
  {
    path: "admin",
    loadComponent: () => {
      console.log("  loadComponent(admin) called");
      return Promise.resolve(AdminComponent);
    },
  },
  {
    path: "shop",
    loadChildren: () => {
      console.log("  loadChildren(shop) called");
      return Promise.resolve([{ path: "orders", component: OrdersComponent }]);
    },
  },
  { path: "**", redirectTo: "" },
];

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

@Component({
  selector: "app-root",
  imports: [RouterOutlet, RouterLink],
  template: `
    <nav>
      <a routerLink="/">Home</a> | <a routerLink="/admin">Admin</a> |
      <a routerLink="/shop/orders">Orders</a>
    </nav>
    <router-outlet />
  `,
})
export class AppComponent {
  readonly router = inject(Router);
  constructor() {
    this.router.events.subscribe((e) => {
      if (e instanceof RouteConfigLoadStart) console.log(`  RouteConfigLoadStart ${e.route.path}`);
      if (e instanceof RouteConfigLoadEnd) console.log(`  RouteConfigLoadEnd   ${e.route.path}`);
      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 77 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 nextMedium

What is content projection and ng-content?

Continue