Angular Design Pattern-Lazy loading feature modules
Tags: angular, typescript, javascript
Published: 2022-02-15 05:26:48

###Introduction###


By default, angular modules are eagerly loaded, which means that all feature modules are loaded as soon as the application loads whether or not they are immediately necessary.

###Why###

For large applications with lots of routes, user might not visit all of them frequently. So loading required modules on demand helps keep initial bundle sizes smaller, which in turn helps decrease load times.

###How it is with eager loading###

Assuming you have an application with a feature module(`Itemsmodule`). This is how your application routes looks like with an _Eager loading_ design pattern.

If you look at below code, its basically telling Angular to load `ItemComponent` on the screen whenever user navigates to `/items`

```javascript
const routes: Routes = [
  { path: 'items', component: ItemComponent }
];
```
And you would have `ItemsModule` under imports of `AppModule`

_app.module.ts_
```javascript
const routes: Routes = [
  { path: 'items', component: ItemComponent }
];

@NgModule({
  declarations: [AppComponent],
  imports: [
    ItemsModule,
    RouterModule.forRoot(routes)
  ]
})
export class AppModule {
  constructor() {}
}
```
With this, `ItemsModule` will be loaded as soon as the application loads.

###How it would be with lazy loading###
Now lets look how this can be done with lazy loading design pattern.

To lazy load Angular modules, use `loadChildren `instead of `component` in your `routes` configuration as shown below.

> 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.

```javascript
const routes: Routes = [
  {
    path: 'items',
    loadChildren: () => import('./items/items.module').then(m => m.ItemsModule)
  }
];
```
And you would then remove `itemsModule `from `app.module.ts` as we no longer loading it on initial load.

_app.module.ts_

```javascript
const routes: Routes = [
  {
    path: 'items',
    loadChildren: () => import('./items/items.module').then(m => m.ItemsModule)
  }
];
@NgModule({
  declarations: [AppComponent],
  imports: [
    RouterModule.forRoot(routes)
  ]
})
export class AppModule {
  constructor() {}
}
```

Looks confusing? it does at first, but all its telling to Angular is, "whenever user visits `/items` only then load `itemsModule`"

Now, there is one more step to understand, so far we have only loaded `itemsModule` at `app.module.ts` level. We are yet to mention which component in `itemsModule` has to be loaded when user visits `/items`. 

To do that, we have to go inside the feature module(`itemsModule`) to mention which component to load.

_items.module.ts_
```javascript
const routes: Routes = [
  {
    path: '',
    component: ItemComponent
  }
];
@NgModule({
  imports: [ RouterModule.forChild(routes) ]
})
export class ItemsModule {
  constructor() {}
}
```

The `path` here is set to an empty string because the path in `AppRoutingModule` is already set to `/items`.

> Every route in this feature module is a child route.

So if you need something like `/items/frequent`, you just have to define that child route inside feature module like shown below.

_items.module.ts_
```javascript
const routes: Routes = [
  {
    path: '',
    component: ItemComponent
  },
{
    path: '/frequent',
    component: FrequentComponent
  }
];
@NgModule({
  imports: [ RouterModule.forChild(routes) ]
})
export class ItemsModule {
  constructor() {}
}
```

So now, `/items` takes user to `ItemComponent `and `/items/frequent` takes user to `FrequentComponent`

yay!!! Now you understood Lazy loading design pattern. Angular docs have an excellent detailed explanation on this topic. I would recommend to read it.

For a sample application with two lazy-loaded modules see the [live example](https://angular.io/generated/live-examples/lazy-loading-ngmodules/stackblitz.html) taken straight out of Angular docs.