In Angular, what changes when you add withPreloading(PreloadAllModules) to provideRouter, and when does the router start preloading?
answer
- default is no preloading
- after each NavigationEnd
- walks the whole route config
- loadChildren and loadComponent both
- errors swallowed, retried later
basics
~10 sBy default the router uses NoPreloading, so lazy chunks download only on navigation. withPreloading(PreloadAllModules) makes the router, after each completed navigation, download every lazy loadChildren and loadComponent chunk in the background.
solid answer
~40 sWithout a preloading feature, the router's strategy is `NoPreloading`: a lazy route's chunk downloads only when a navigation needs it. `provideRouter(routes, withPreloading(PreloadAllModules))` swaps in `PreloadAllModules`. The router's preloader listens for `NavigationEnd`; after the first navigation completes, and after every later one, it walks the route configuration and asks the strategy whether to load each not-yet-loaded `loadChildren` and `loadComponent` route, recursing into child routes as they arrive. `PreloadAllModules` says yes to all of them and swallows load errors, so a failed preload does not break the app and the route is simply tried again later. Routes guarded by the deprecated `canLoad` are skipped for `loadChildren`; `canMatch` does not prevent preloading.
code
ts · 7 linesimport { ApplicationConfig } from '@angular/core';
import { PreloadAllModules, provideRouter, withPreloading } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes, withPreloading(PreloadAllModules))],
};go deeper
Remember that Angular does not preload by default and that withPreloading(PreloadAllModules) downloads lazy routes in the background.
Explain that preloading runs after each NavigationEnd, covers loadChildren and loadComponent, recurses into loaded children and swallows errors.
Judge when preloading everything costs more than it saves, and know that canMatch does not stop preloading while canLoad does.
Decide a preloading policy per audience and network, balancing faster navigation against bandwidth, memory and competing startup work.
## The default: nothing is preloaded The router has a pluggable **`PreloadingStrategy`**. Unless you configure one, it uses **`NoPreloading`**, whose `preload()` returns `of(null)` for every route. Lazy chunks are then fetched only on demand: the first click on `/reports` waits for the reports chunk to download and evaluate. ## Turning on `PreloadAllModules` ```ts bootstrapApplication(App, { providers: [provideRouter(routes, withPreloading(PreloadAllModules))], }); ``` `withPreloading()` takes a strategy **class** (a `Type<PreloadingStrategy>`) and also registers the router's preloader. In NgModule-era code the same thing is `RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })`. ## When preloading actually runs The preloader is event-driven, not timer-driven: 1. It subscribes to `Router.events` and reacts to every **`NavigationEnd`**. 2. On each one it walks the **entire route configuration**, starting from the root routes. 3. For each route that has a `loadChildren` not yet loaded, or a `loadComponent` not yet loaded, it calls the strategy's `preload(route, load)`. 4. When a `loadChildren` chunk arrives, it continues into the newly loaded child routes, so nested lazy areas are preloaded too. 5. Runs are queued one after another, so a second `NavigationEnd` does not start a competing walk while one is in progress. In practice this means preloading starts **right after the initial navigation completes**, so it does not compete with the first route's own chunk and data, and it keeps catching up after later navigations (for example on routes that only appear after a lazy area has loaded). ## What `PreloadAllModules` does and does not do - It calls `load()` for **every** eligible route, as fast as the network allows. - It **catches errors** from each load and turns them into `null`. A failed preload is silent; nothing is cached for that route, so a later preload pass or the user's own navigation tries it again. - It loads both `loadChildren` and `loadComponent` routes. Only `loadChildren` routes with a **`canLoad`** guard are skipped, because `canLoad` guards can have side effects and the preloader will not run them. `canLoad` is deprecated in favour of `canMatch`, and **`canMatch` does not stop preloading**. - It does not preload `@defer` blocks inside templates; those are a separate mechanism. | Strategy | What loads in the background | Good fit | |---|---|---| | `NoPreloading` (default) | nothing | very large apps, metered or slow connections | | `PreloadAllModules` | every lazy route | small or medium apps where total code is modest | | custom `PreloadingStrategy` | whatever `preload()` decides | large apps, role-specific sections, data-flagged routes | ## What preloading does not do Preloading only fetches and evaluates code. The preloader runs each route's loader (inside the route's injection context, creating the route's environment injector first if the route has `providers`), but it does **not** create components, run `canMatch` or `canActivate` guards, or call resolvers. So preloading a reports area never triggers its data requests; those still happen when the user actually navigates there. It also means preloading cannot know whether the user is allowed into a section, which is why role-dependent preloading needs a custom strategy. ## Trade-offs to state in an interview - **Faster later navigations**: the chunk is already in memory when the user clicks. - **Higher total transfer and memory**: users download code for sections they may never open. On mobile or metered networks that is a real cost. - **Competition**: preloading can compete with images, API calls and other work that happens right after the first render. - **It does not shrink the initial bundle**: preloading only changes *when* lazy chunks download, not what the first page needs. The usual progression is to start with `PreloadAllModules` while the app is small and move to a custom strategy once some sections are large or only relevant to some users.
- Does a canMatch guard on the reports route stop PreloadAllModules from downloading the reports chunk?No. The preloader skips `loadChildren` routes only when they have a `canLoad` guard, which is deprecated. `canMatch` guards run during navigation matching, so they stop a navigation from downloading the chunk, but not the preloader. Use a custom strategy if a section should not be preloaded for some users.
- What happens if a preload request fails because the network drops?`PreloadAllModules` catches the error and emits `null`, so nothing is thrown and the route stays unloaded. Because the preloader walks the configuration again after the next `NavigationEnd`, and the user's own navigation also loads on demand, the chunk is retried later.
PreloadAllModules is like a shop assistant who, once you have been served, fetches every remaining item on the shelf list from the stockroom so the next request is instant, whether or not you ever ask for it.
saying these in an interview costs you the question
- PreloadAllModules shrinks the initial bundle
- Preloading starts before the first navigation to save time
- PreloadAllModules only preloads loadChildren, never loadComponent
- canMatch guards stop preloading like canLoad did
- Angular preloads lazy routes by default