Angular Lazy Loading Feature Modules

Feature Module

In this article I am implementing the process of lazy loading feature modules in Angular application.

In programming language, a module is a self-contained unit of code that performs a specific task or provides a set of related functions. It is a way of organizing and managing code in a modular and reusable manner.

A module can be a separate file or a collection of files that contain functions, classes, variables, or other code components. It encapsulates a specific set of functionalities, making it easier to understand, test, and maintain code.

In Angular, a feature module is a way to organize and encapsulate a specific set of features and functionality within an application.

A feature module contains a group of related components, directives, services, and a few other files. It helps us maintain and manage the application codebase.

Routing

A routing in Angular is a mechanism that allows you to navigate between different views and components in an Angular application. It helps you build single-page applications by dynamically changing the content displayed on the page without reloading the entire page. Instead of traditional server-side routing, where the server handles navigation and page loads, a routing in Angular handles navigation on the client-side.

Purpose of Lazy loading

Lazy loading is essential for optimizing the performance and user experience of your application. It allows your application to load only the modules and components if user navigates through them. Lazy loading is a technique that allows user to defer loading of certain parts of an angular application.

Prerequisites

Angular 20, Npm 10.9.2, Node 22.17.0

Implementing Lazy Loading

In Angular application you need to create feature modules that encapsulate specific parts of your application. These modules can be loaded independently, and you can specify which modules should be lazy-loaded based on the routes.

Create New project

Create a new project by executing the following command:

ng new angular-feature-module-lazy-loading --no-standalone

Create Feature Modules and Components

Create a feature module called users. Navigate into the project directory angular-feature-module-lazy-loading and create the feature module users by running the following command:

ng generate module users --route users --module app-module

This creates a users directory having the new lazy-loadable feature module UsersModule defined in the users.module.ts file and the routing module UsersRoutingModule defined in the users-routing.module.ts file. The command automatically declares the Users component and imports UsersRoutingModule inside the new feature module.

Because the new module is meant to be lazy-loaded, the command does not add a reference to it in the application’s root module file, app.module.ts. Instead, it adds the declared route, users to the routes array declared in the module provided as the --module option.

This will generate a new module named users-module.ts under the users directory, along with a routing module named users-routing-module.ts specific to this module.

src/app/users/users-routing-module.ts
src/app/users/users-module.ts

It will generate the component for users module:

src/app/users/users.spec.ts
src/app/users/users.ts
src/app/users/users.css
src/app/users/users.html

The behavior of the ng generate component command in Angular, specifically regarding the appending of “component” to the file name, has changed with recent Angular versions.

Previous Behavior (Angular versions prior to 20):

In older versions of Angular, when you used ng generate component , the generated files would include the .component suffix in their names. For example, ng generate component app would create app.component.ts, app.component.html, app.component.css, and app.component.spec.ts.

Current Behavior (Angular 20 and later):

With Angular 20 and newer versions, the naming convention has been updated to align with new style conventions. The .component suffix is no longer automatically appended to the file names by default. Instead, ng generate component app will now produce files like app.ts, app.html, app.css, and app.spec.ts. This change aims to simplify file names and is part of a broader shift in Angular’s coding style guidelines.

And it will update the following app routing module file to include the lazy-loadable path for the users module.

src/app/app-routing-module.ts

The following path in the routes constant gets added in the above file:

const routes: Routes = [{ path: 'users', loadChildren: () => import('./users/users-module').then(m => m.UsersModule) }];

Notice that the lazy-loading syntax uses loadChildren followed by a function that uses the browser’s built-in import('…') syntax for dynamic imports. The import path is the relative path to the module.

Generate another component user-detail under users directory by executing the following command:

ng generate component users/user-detail

This will create a new component named user-detail within the users module.

src/app/users/user-detail/user-detail.spec.ts
src/app/users/user-detail/user-detail.ts
src/app/users/user-detail/user-detail.css
src/app/users/user-detail/user-detail.html

And it will update the following module file to include the generated user-detail component.

src/app/users/users-module.ts

Next is to configure the routing for users module. Open the users-routing.module.ts file under the users directory and modify it as follows:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Users } from './users';

const routes: Routes = [
  { path: '', component: Users },
  { path: 'user/:id/detail', component: UserDetail }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class UsersRoutingModule { }

Create another feature module products. Again navigate into the project directory angular-feature-module-lazy-loading and create the feature module products by running the following command:

ng generate module products --route products --module app-module

This will generate a new module named products-module.ts under the products directory, along with a routing module named products-routing-module.ts specific to this module.

src/app/products/products-routing-module.ts
src/app/products/products-module.ts

This will create a new component named products within the products directory.

src/app/products/products.spec.ts
src/app/products/products.ts
src/app/products/products.css
src/app/products/products.html

And it will update the following app routing module file to include the lazy-loadable path for the products module.

src/app/app-routing-module.ts

The following path in the routes constant gets added in the above file:

const routes: Routes = [
  { path: 'users', loadChildren: () => import('./users/users-module').then(m => m.UsersModule) },
  { path: 'products', loadChildren: () => import('./products/products-module').then(m => m.ProductsModule) }
];

Generate another component product-detail under products directory by executing the following command:

ng generate component products/product-detail

This will create a new component named product-detail within the products module.

src/app/products/product-detail/product-detail.spec.ts
src/app/products/product-detail/product-detail.ts
src/app/products/product-detail/product-detail.css
src/app/products/product-detail/product-detail.html

And it will update the following module file to include the generated product-detail component.

src/app/products/products-module.ts

Now configure the routing for products module. Open the products-routing.module.ts file under the products directory and modify it as follows:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { Products } from './products';
import { ProductDetail } from './product-detail/product-detail';

const routes: Routes = [
  { path: '', component: Products },
  { path: 'product/:id/detail', component: ProductDetail },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ProductsRoutingModule { }

Here I use lazy loading using loadChildren property in this example to navigate features modules based on navigations.

By using lazy loading, you can split your application into smaller, more manageable chunks, improving performance by loading modules only when they are required. This approach is particularly useful for larger applications or when you have sections of your application that are accessed less frequently.

Lazy-loaded modules are loaded asynchronously and cached by the Angular router, so subsequent visits to the same route will load the module from the cache instead of making a new request to the server.

Update the app.html file as follows:

<h1>
  {{ title() }}
</h1>

<button type="button" routerLink="/users">Users</button> &nbsp;
<button type="button" routerLink="/products">products</button>

<router-outlet />

In the Users component, in the file users.html, I have written the routerLink as follows:

<h4>User List Component</h4>

<button type="button" [routerLink]="['/users', 'user', '123', 'detail']">User Details</button>

Here I used button with a router link for navigation purpose and, at the bottom, a router outlet to render different components of the feature module based on navigation.

The [routerLink] attribute can be bound to an expression, and in the [routerLink]="['/users', 'user', '123', 'detail'] the expression is ['/users', 'user', '123', 'detail']. This expression is an array of path segments, where each element represents a part of the route URL.

Let’s break down the expression:

  • ‘/users’: Representing the parent route. It indicates that the navigation will happen relative to the ‘users’ route
  • ‘user’: Representing the child route. It indicates that we want to navigate to the ‘user’ route, which is a child route of the ‘users’ route. So, the complete child route is user/123/detail.

Verify lazy loading

You can verify that a module is indeed being lazy loaded with the Chrome developer tools. In Chrome, open the developer tools by pressing Cmd+Option+i on a Mac or Ctrl+Shift+j on a PC and go to the Network Tab.

Click on the Users or Products button. If you see a chunk appear, everything is wired up properly and the feature module is being lazy loaded. A chunk should appear for Users and for Products but only appears once for each.

Chunk for Users module

Here is the screenshot for chunk of Users module:

chunk

Chunk for Products module

Here is the screenshot for the chunk of Products module:

chunk

Testing Lazy Loading

Here is the home page at URL http://localhost:4200, once you run the application by executing command ng serve:

angular lazy loading

Now you can click on Users or Products button and verify if everything works as expected.

Source Code

Download

Share

No comments

Leave a comment