Angular 6 Lazy Loading with demo

angular 6 lazy loading not working angular 6 lazy loading modules angular lazy loading components angular cli lazy loading angular 5 lazy loading angular 2 lazy loading webpack what is lazy loading in angular 2 angular 6 lazy loading cannot find module

Lazy loading in angular is introduced to load the source and pages on demand. Concept is to group the feature in modules and when user load any page from that module, load the complete module only then rather than to load everything on application start.

Let's try to understand the concept with example: Say we have a website which have users, customers, products etc. For lazy Loading, we will keep all the users related information in Users module, similarly for the customers and products. When user will hit the home page, only basic information will be loaded and not the user, customer and product. When user will hit any page from any module that module will load at that time.

How can we acheive it: there are three main steps:

  • Create a separate folder for module
  • Create routing for the module
  • Configure the routes for module

In this article we will see this with example:

  • customers
    • customer-list
      • customer-list.component.html
      • customer-list.component.ts
    • customer-detail
      • customer-detail.component.html
      • customer-detail.component.ts
    • customer.component.ts
    • customer-routing.module.ts
    • customer-module.ts
  • products
    • product-list
      • product-list.component.html
      • product-list.component.ts
    • product-detail
      • product-detail.component.html
      • product-detail.component.ts
    • product.component.ts
    • product-routing.module.ts
    • product-module.ts

Here we created two modules, customers and products, what it contains:

  • Customer List
  • Customer Detail
  • Customer Component: to load as default page for the module
  • Customers-Routing.Module: Routing for customers module
  • Customers.Module: Configure the customer module

Similarly we will do for anyother modules, products.

I used-to to create components folder and keep all the compnent in that. It is not mandatory so we will not discuss that but you will not that folder in different places.

Angular 6 lazy loading with examples

Let's create the customer module, Customer List Component: We will use hardcoded list of customers for example otherwise it need to come from database through server.

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-customer-list',
  templateUrl: './customer-list.component.html'
})
export class CustomerListComponent implements OnInit {
  customerList: Array<any>;
  constructor() { }
  ngOnInit() {
    this.customerList = [
     {"id":100,"name":"John Smith","city":"Aylesbury","country":"Greece","zipcode":22101},
     .................
    ]
  }
}

Template for Customer List, to show the list of customers.

<h3>Customers List</h3>
<div class="row">
  <div class="col-sm-12">
    <table class="table table-bordered">
      <tr>
        <th>ID</th>
        <th>Name</th>
        <th>City</th>
        <th>Country</th>
        <th style="white-space: nowrap;">Zip Code</th>
      </tr>
      <tr *ngFor="let item of customerList">
        <td>{{item.id}}</td>
        <td><a routerLink="{{item.id}}/detail">{{item.name}}</a></td>
        <td>{{item.city}}</td>
        <td>{{item.country}}</td>
        <td>{{item.zipcode}}</td>
      </tr>
    </table>
  </div>
</div>

Note the Name column is a link, which will open the detail page, so let's create the detail component, here is the code for customer detail component

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
  selector: 'app-customer-detail',
  templateUrl: './customer-detail.component.html'
})
export class CustomerDetailComponent implements OnInit {
  customerRecord: any;
  // hard coded list of customers
  customerList:Array<any> = [......];
  constructor(private route: ActivatedRoute) { }
  ngOnInit() {
    this.route.params.subscribe(params => {
      var id = params['id'];
      this.getCustomer(id);
    });
  }
  getCustomer(id){
    this.customerRecord = this.customerList.filter(x=>x.id == id)[0];  
  }  
}

Customer detail componente template (html), simply using bootstrap row and col-x to show the detail:

<h1>Customer Detail</h1>
<div class="row mb-2">
  <td class="col-3"><strong>ID</strong></td>
  <td class="col-9">{{customerRecord.id}}</td>
</div>
<div class="row mb-2">
  <td class="col-3"><strong>Name</strong></td>
  <td class="col-9">{{customerRecord.name}}</td>
</div>
<div class="row mb-2">
  <td class="col-3"><strong>City</strong></td>
  <td class="col-9">{{customerRecord.city}}</td>
</div>
<div class="row mb-2">
  <td class="col-3"><strong>Country</strong></td>
  <td class="col-9">{{customerRecord.country}}</td>
</div>
<div class="row mb-2">
  <td class="col-3"><strong>Zip Code</strong></td>
  <td class="col-9">{{customerRecord.zipcode}}</td>
</div>

If you want a defulat template, might be if you want to change the design or something, so simply create a container component with module name, in this case "Customer.Component.ts", and here is the complete code because we are using inline template here:

import { Component } from '@angular/core';
@Component({
  selector: 'app-customers',
  template: '<router-outlet></router-outlet>'
})
export class CustomersComponent{
  constructor() { }
}

Note the router-outlet, we need it to render the child component in it.

Nitll now there is nothing special about lazy loading, we just created three components in angular 6, so no need to explain any thing.

Now we need to create the routing for this module, for which we need to create a module ng g module customers-routing --flat -t -s, here is the complete code for customers-routing module:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';

import { CustomersComponent } from './customers.component';
import { CustomerListComponent } from './customer-list/customer-list.component';
import { CustomerDetailComponent } from './customer-detail/customer-detail.component';

const routes: Routes = [
  {
    path: '', 
    component: CustomersComponent,
    children: [
      { path: ':id/detail', component: CustomerDetailComponent },
      { path:'', component: CustomerListComponent }
    ]
  }
]
@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild(routes)
  ],
  exports:[RouterModule],
  declarations: [CustomersComponent, CustomerListComponent, CustomerDetailComponent ]
})
export class CustomersRoutingModule { }

What to nete here:

  • Imported all the components created in this module
  • Created parent child routing
  • See imports, we used here RouterModule.forChild(..)
  • Put all the components in declarations

Finally we need to create the ng g module customers --flat, here is the complete code of Customers.Module.ts file:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { CustomersRoutingModule } from './customers-routing.module';

@NgModule({
  imports: [
    CommonModule, 
    CustomersRoutingModule
  ],
  declarations: []
})
export class CustomersModule { }

What to note here:

  • imported `CustomersRoutingModule' our created routing for this module
  • Put this inside the imports array
  • note, declarations are empty

We need to create routing for application say it app-routing.module to create it run ng g module app-routing --flat. Here is the code for app-routing.module.ts file:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';

import {AppComponent} from './app.component';
import { HomeComponent } from './components/home/home.component';

const mainRoutes: Routes = [
  {
    path:'customers',
    loadChildren: '../app/components/customers/customers.module#CustomersModule'
  },
  {
    path:'',
    redirectTo:'',
    pathMatch:'full',
    component: HomeComponent
  }
]
@NgModule({
  imports: [
    CommonModule,
    RouterModule.forRoot(mainRoutes)
  ],
  exports:[RouterModule],
  declarations: [HomeComponent]
})
export class AppRoutingModule { }

Points to note here:

  • I have created a home component for home page, I will copy the code latter it's very simple page with heading and text
  • Lazy loading module will by loadChildren
  • Path of the module file followed by # with module class name

    { path:'customers', loadChildren: '../app/components/customers/customers.module#CustomersModule' }

  • For default we use the home component

    { path:'', redirectTo:'', pathMatch:'full', component: HomeComponent }

  • In this module we will use RouterModule.forRoot(mainRoutes), note forRoot inplace of forChild which we used in our lazy loading module.
  • Very important: not to import any lazy loading module here otherwise that module will load the the time of application start

We need use this app-routing.module into our app.module

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Note we are not importing or decalring any module or component from the lazy loading features, just the appComponent to bootstrap the application and AppRoutingModule to load the basic resources.

For clarity, let's add app.component.ts and app.component.html template file:

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent { }
// Template File
<div class="container">
  <button routerLink="" class="btn btn-sm btn-link">Home</button>
  <button routerLink="/customers" class="btn btn-sm btn-link">Customer</button>
  <button routerLink="/products" class="btn btn-sm btn-link">Products</button>
  <hr />   
  <router-outlet></router-outlet>
</div>

I used here buttons for exmaple, you can create a separate navigation component for top menu and use what ever html elements you want and import that.

Note the router-outlet to render the rest of the pages and menu will be as it is.

Index.html file have nothing special except <app-root ></app-root>

I promise to copy the home.component so here the code for ts and html file

import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html'
})
export class HomeComponent {
  constructor() { }
}
// Html
<h1>Home</h1>
<hr>
<div class="row">
  <div class="col-sm-6">
    <h4>What is Lorem Ipsum?</h4>
    <p>Lorem Ipsum is simply...</p>
  </div>
  <div class="col-sm-6">
    <h4>Why do we use it?</h4>
    <p>It is a long established...</p>
  </div>
</div>
<div class="row">
  <div class="col-sm-6">
    <h4>Where does it come from?</h4>
    <p>Contrary to popular belief...</p>
  </div>
  <div class="col-sm-6">
    <h4>Where can I get some?</h4>
    <p>There are many variations of...</p>
  </div>
</div>

Let's run the application see everything is working, run the command `ng serve'

Greate everything is working but I missed the bootstrap file to include. There are two way to use the bootstrap, either by using the CDN or by installing it.

If you are using CDN then open the style.css file and add

@import "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css";

Otherwise install it by npm i --save-dev bootstrap, after installing it we need to reference it inside the angular.json file:

"build": {
  .........
  "styles": [
              "./node_modules/bootstrap/dist/css/bootstrap.css",
              "src/styles.css"
        ]
}

We added two modules 1. Customer and 2. Products, we completed for customers so now we will create together complete products lazy loading module step be step and will practice it.

  • Create a new folder products inside components folder.
  • Go to products folder cd products
  • Create a component product-list.component ng g component product-list -s

Create a dummy list of products say productList: Array = [...] and adjust the html to show the list in tabular format, see customer list code.

Similar to product list create product detail page and read the id from route and select a product from your dummy list ( you need to copy the dummy list here as well).

Create a products component in products folder ng g component products -s -t --flat, here flat: means in current directory, t: means inline template, s: means inline style. means everything in products.component.ts file. After changing and removing unnesessary code, it will become:

import { Component } from '@angular/core';
@Component({
  selector: 'app-products',
  template: `<router-outlet></router-outlet>`
})
export class ProductsComponent { }

We need to create the routing for this module as well, so create a products-routing.module by using command ng g module products-routing

All the components created with ng commoand will automatically be imported into app.module.ts file, copy and remove every import of product related components and add to product-routing.module.ts file:

import { Routes, RouterModule } from '@angular/router';
import { ProductsComponent } from './products.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductDetailComponent } from './product-detail/product-detail.component';

Create a variable say productRoutes and define the routes like this:

const productRoutes: Routes = [
  {
    path: '', 
    component: ProductsComponent,
    children: [
      { path: ':id/detail', component: ProductDetailComponent },
      { path:'', component: ProductListComponent }
    ]
  }
]

Inside the import add RouterModule.forChild(productRoutes) and add all the components in declarations, now @NgModule will become

@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild(productRoutes)
  ],
  declarations: [ProductsComponent, ProductListComponent, ProductDetailComponent ]
})
export class ProductsRoutingModule { }

One more file we need to add in this module call product.module.ts, create it by running the command ng g module products --flat. After creating it, import our ProductRoutingModule and pass that in imports.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
//Added
import { ProductsRoutingModule} from './products-routing.module'; 

@NgModule({
  imports: [
    CommonModule,
    ProductsRoutingModule  // Added
  ],
  declarations: []
})
export class ProductsModule { }

Open our app-routing.module.ts file and add routing for products (lazy loading). No need to import anything just add following lines after customers routing:

{
  path:'products',
  loadChildren: '../app/components/products/products.module#ProductsModule'
},
Ali Adravi Having 13+ years of experience in Microsoft Technologies (C#, ASP.Net, MVC and SQL Server). Worked with Metaoption LLC, for more than 9 years and still with the same company. Always ready to learn new technologies and tricks.
  • angular
  • lazy-loading
  • routing
By Ali Adravi On 30 Jul, 18  Viewed: 1,067

Other blogs you may like

Angularjs powerful paging on table and searching with delay and demo

Paging on table is the basic requirement and most of us look for some grid so it can provide the complete feature of paging and sorting but in Angularjs it is so easy that anyone can achieve it by writing some code. I checked and found most of the available code give the paging feature in for 1 to... By Ali Adravi   On 14 Aug 2015  Viewed: 13,709

Angularjs Cascading Dropdown/Select with demo

Cascading dropdown with angularjs is easier than MVC and ASP.Net. In Angularjs ng-change is the best event to hook the function to get the second dropdown list items. In this article, we will try to fill the state dropdown on selection change of country and then fill the city dropdown on change... By Ali Adravi   On 06 Aug 2015  Viewed: 48,794

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 2

Add/Edid Customer in Modal Popup --- In previous article we discussed how to search, delete and show detail of customer and contact list. In this article we will try to open the modal popup to add new customer and edit an existing customer record. I divided article in two parts because of the... By Ali Adravi   On 29 Jul 2015  Viewed: 17,493

Custom Directives in AngularJS with example and demo

Angularjs custom directives are the common to avoid the duplicate code, it is easy powerful and really nice. There are already too many directive have been created by experts but as a developer we need to write our own to achieve our specific goal. ng-model, ng-if, ng-show, ng-repeat all these are... By Ali Adravi   On 29 Jul 2015  Viewed: 3,908

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 1

Search sort Insert update and delete are the basic features we need to learn first to learn any language, In this article we will try to create these features with Web API, bootstrap modal popup and ui.router. We will use enetity framework code first to save and retrieve data from database. We... By Ali Adravi   On 28 Jul 2015  Viewed: 28,947