As Angular applications grow larger, they often include multiple features, pages, and components. Loading all of these modules at once can lead to slow application startup and negatively impact user experience. To address this challenge, Angular provides a mechanism called lazy loading, which allows modules to be loaded on demand rather than at startup.
Lazy loading improves performance, reduces the initial bundle size, and organizes large applications effectively. In this comprehensive guide, we will cover:
- Introduction to lazy loading in Angular
- Benefits of lazy-loaded modules for app performance
- Step-by-step configuration of lazy-loaded routes using
loadChildren
- Best practices for using lazy loading in Angular applications
What Is Lazy Loading?
Lazy loading is a design pattern where certain parts of the application, such as feature modules, are loaded only when they are needed, rather than during the initial application startup. In Angular, lazy loading is implemented using feature modules and the Angular Router.
Key Features of Lazy Loading
- On-Demand Module Loading: Modules are fetched only when users navigate to routes that require them.
- Smaller Initial Bundle: Reduces the size of JavaScript that the browser downloads at startup.
- Improved Performance: Faster initial load times and better user experience.
- Separation of Concerns: Feature modules remain isolated and self-contained, improving maintainability.
Why Lazy Loading Improves Performance
Without lazy loading, Angular bundles all modules into a single JavaScript file by default. For small apps, this is fine, but for larger applications, it can create longer load times:
- Large bundle size → slower first paint
- Users may never need all features immediately
- Initial load performance becomes critical for mobile users
Lazy loading addresses these issues by:
- Loading only essential modules initially
- Fetching feature modules on-demand as users navigate
- Reducing memory usage and network consumption
Prerequisites for Lazy Loading
Before implementing lazy loading, ensure:
- Your application uses Angular Router.
- Features are organized into modules (feature modules).
- Feature modules are self-contained and optionally include their own routing module.
Step-by-Step Guide to Configuring Lazy-Loaded Modules
Step 1: Generate a Feature Module
Use Angular CLI to create a feature module:
ng generate module products --route products --module app.module
Explanation:
products
→ Name of the module--route products
→ Automatically sets up a route for lazy loading--module app.module
→ Adds configuration in the root module
This generates:
src/app/products/
├─ products.module.ts
├─ products-routing.module.ts
└─ components/ (optional components)
Step 2: Structure the Feature Module
products.module.ts
example:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProductsRoutingModule } from './products-routing.module';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductDetailComponent } from './product-detail/product-detail.component';
@NgModule({
declarations: [
ProductListComponent,
ProductDetailComponent
],
imports: [
CommonModule,
ProductsRoutingModule
]
})
export class ProductsModule { }
- declarations → Components specific to this feature
- imports → CommonModule and ProductsRoutingModule for routing
Step 3: Set Up Feature Module Routing
products-routing.module.ts
example:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductDetailComponent } from './product-detail/product-detail.component';
const routes: Routes = [
{ path: '', component: ProductListComponent },
{ path: ':id', component: ProductDetailComponent }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ProductsRoutingModule { }
RouterModule.forChild(routes)
sets up routes specific to the feature module- Root module doesn’t need to know about individual components of the feature module
Step 4: Configure Lazy Loading in App Routing
Update app-routing.module.ts
:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
{ path: 'products', loadChildren: () => import('./products/products.module').then(m => m.ProductsModule) },
{ path: '**', redirectTo: 'home' }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
loadChildren
uses dynamic imports to load modules on demand- Arrow function returns a promise that resolves to the module class
- Angular automatically bundles the module separately for lazy loading
Step 5: Verify Lazy Loading
- Run the application:
ng serve
- Open the Network tab in browser dev tools.
- Navigate to
/products
. You should see a separate chunk loaded dynamically.
Example: Lazy Loading Multiple Feature Modules
Suppose your app has Products and Orders features:
const routes: Routes = [
{ path: 'products', loadChildren: () => import('./products/products.module').then(m => m.ProductsModule) },
{ path: 'orders', loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule) }
];
- Both modules are lazy-loaded
- Only loaded when users navigate to
/products
or/orders
Benefits of Lazy Loading
- Reduced Initial Load Time
- Only essential modules are loaded initially
- Better Performance for Large Apps
- Keeps the main bundle small
- Organized Architecture
- Feature modules remain isolated and self-contained
- Improved User Experience
- Faster first paint and less waiting for users
Advanced Lazy Loading: Preloading Strategy
Angular allows preloading of lazy-loaded modules to balance initial load and navigation speed.
imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })]
- Preloads lazy modules in the background after app loads
- Reduces delay when navigating to lazy-loaded routes
Lazy Loading Best Practices
- Organize Features into Modules
- Only modules that can be loaded independently should be lazy-loaded
- Avoid Lazy Loading Tiny Modules
- Lazy loading introduces a slight overhead; don’t lazy-load very small modules
- Keep Routing Self-Contained
- Use
RouterModule.forChild()
inside feature modules
- Use
- Use Preloading for Large Apps
- Improves user experience for routes that are likely to be visited
- Combine with Shared Modules
- Feature modules can import a
SharedModule
for common components and directives
- Feature modules can import a
Leave a Reply