Angular module loading strategies, optimizing user experience
How to implement a module preloading strategy

Front-end software engineer and I specialise in Angular🤖. I've been working with it since Angular JS and I like to keep up with new technologies. I love to write about Angular, TypeScript, JavaScript and more 📰. My hobbies are travelling around Southeast Asia ✈️, cars and technology.
When developing Angular applications, one of the key considerations is how to efficiently load and manage modules. How we handle module loading can have a significant impact on user experience and overall performance. In this post, we'll explore various module loading strategies in Angular and provide practical examples for each of them.
Lazy loading
One of Angular's most powerful features is the ability to load modules on-demand, a concept known as lazy loading. This means modules are loaded only when the user needs them, which can significantly improve initial load times. Below is an example of how this is implemented in the route file AppRoutingModule:
const routes: Routes = [
{
path: "contact",
loadChildren: () =>
import("./contact/contact.module").then((m) => m.ContactModule),
},
{
path: "about",
loadChildren: () =>
import("./about/about.module").then((m) => m.AboutModule),
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
StandAlone API version
export const routes: Routes = [
{
path: "contact",
loadChildren: () =>
import("./contact/contact.routes").then((m) => m.CONTACT_ROUTES),
},
{
path: "about",
loadChildren: () =>
import("./about/about.routes").then((m) => m.ABOUT_ROUTES),
},
];
Directly lazy loading a standalone component
export const routes: Routes = [
{
path: "contact",
loadComponent: () =>
import("./contact/contact.component").then((m) => m.ContactComponent),
},
{
path: "about",
loadComponent: () =>
import("./about/about.component").then((m) => m.AboutComponent),
},
];
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes)],
});
Preload all modules
If you want to preload all modules in your application upfront, you can use the PreloadAllModules strategy. This speeds up user navigation after loading all modules at once. Here's how to enable this strategy:
@NgModule({
imports: [
RouterModule.forRoot(routes, {
preloadingStrategy: PreloadAllModules,
}),
],
exports: [RouterModule],
})
export class AppRoutingModule {}
StandAlone API version
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes, withPreloading(PreloadAllModules))],
});
Custom module preloading
What if you only want to preload specific modules upfront? You can create a custom preloading strategy, loading only the modules that are most crucial for the user experience. Here's an example of a custom preloading strategy:
@Injectable({
providedIn:'root'
})
export class PreloadingStrategyService implements PreloadingStrategy {
private preloadedModules: string[] = [];
preload(route: Route, load: () => Observable): Observable {
if (route.data && route.data['preload'] && route.path) {
this.preloadedModules.push(route.path);
return load();
} else {
return of(null);
}
}
}
const routes: Routes = [
{
path: "contact",
loadChildren: () =>
import("./contact/contact.module").then((m) => m.ContactModule),
},
{
path: "about",
loadChildren: () =>
import("./about/about.module").then((m) => m.AboutModule),
data: { preload: true },
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, {
preloadingStrategy: PreloadingStrategyService,
}),
],
exports: [RouterModule],
})
export class AppRoutingModule {}
StandAlone API version
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes, withPreloading(PreloadingStrategyService))],
});
Using ngx-quicklink
Another interesting option is the ngx-quicklink library, which loads modules as the links appear on the screen. This enhances user-perceived speed by loading modules in the background. To use it, you first need to install the library:
npm i ngx-quicklink
Then, you can enable it as follows:
import { QuicklinkStrategy } from "ngx-quicklink";
@NgModule({
imports: [
RouterModule.forRoot(routes, {
preloadingStrategy: QuicklinkStrategy,
}),
],
exports: [RouterModule],
})
export class AppRoutingModule {}
StandAlone API version
import { quicklinkProviders, QuicklinkStrategy } from 'ngx-quicklink';
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes, withPreloading(QuicklinkStrategy)),
quicklinkProviders
]
})
Import the QuicklinkDirective in all your standalone components that use preloading:
import { RouterModule } from '@angular/router';
import { QuicklinkDirective } from 'ngx-quicklink';
@Component({
standalone: true,
imports: [RouterModule, QuicklinkDirective],
template: `
<a routerLink="/form">Form</a>
`,
})
Conclusion:
In summary, Angular offers several module loading strategies to optimize user experience and application performance. The choice of the right strategy depends on the specific needs of your project. Lazy loading, preloading, custom loading, and ngx-quicklink are powerful tools you can use to ensure your users enjoy a smooth and fast experience.
Explore these strategies and choose the one that best suits your requirements!






