Angular: Lazy Loading

Contents

Scalable Angular Application Architecture

Scalable Angular Application Architecture

  • Angular can only enforce the basics of application architecture. (small or medium applications)
  • Big applications:
    • composed of dozens of modules.
    • filled with complex data collections and complicated user flows.
    • developed by a team across different countries.

In order to maintain high quality

  • Project structure – how to organize you project files, define and work with Angular modules and their dependencies
  • Data flow architecture – devise a guide on how to define that way the data flows through your application layers
  • State management – how to manage the state of GUI and propagate it between different application parts

Structure of the application

Structure of the application - I

  • Usually, one of the first things you do when you set up a new project is to define the structure of the application.

Structure of the application - II

  • An application must follow the module-oriented project structure.
  • Every module directory contains all files (code, styles, templates etc.) that are related to a given module.

Structure of the application - III

  • AppModule – the bootstrapping module
  • CoreModule – global services.
  • SharedModule – usually a set of components or services that will be reused in other modules.
  • Features - All remaining modules should be isolated and independent.

Structure of the application - IV

  • One of the most visible performance problems that users may encounter is the loading time of the application.
  • There are multiple ways in which we can reduce the size of the application bundle, however, those are not within the subject matter of this talk.

What is Lazy Loading?

“ Lazy loading is a design pattern commonly used to defer initialization of an object until the point at which it is needed. (source: wikipedia) ”

The benefits are

  • Keep the initial payload small
  • Smaller payloads lead to faster download speeds
  • Lower resource costs especially on mobile networks
  • If a user doesn't visit a section of our app, they won't ever download those resources

Frontend: Heroes Tour

                            
                                    $ cd 00-tour-heroes
                                    $ npm install
                                    $ npm start
                            
                        

Heroes Tour: Dashboard

Heroes Tour: List of Heroes

Angular: Lazy Loading

Create SharedModule and CoreModule - I

                              
                                  const SHARED_MODULES = [
                                    CommonModule,
                                    FormsModule,
                                    HttpClientModule,
                                    //Interesting modules :-)
                                    /*  InlineEditorModule, */
                                  ];
                                  const SHARED_COMPONENTS: any[] = [];
                                  
                                  @NgModule({
                                    imports: [...SHARED_MODULES],
                                    exports: [...SHARED_MODULES, ...SHARED_COMPONENTS],
                                    declarations: SHARED_COMPONENTS,
                                  })
                                  export class SharedModule { }
                            
                        

Create SharedModule and CoreModule - II

                                  
                                      export const CORE_SERVICES: any[] = [HeroService];
                                      @NgModule({
                                        imports: [
                                          NoopAnimationsModule,
                                          HttpClientInMemoryWebApiModule.forRoot(
                                            InMemoryDataService, { dataEncapsulation: false }
                                          )
                                        ],
                                        providers: CORE_SERVICES,
                                      })
                                      export class CoreModule {
                                        constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
                                          if (parentModule) {
                                            throw new Error("CoreModule is already loaded. Import it in the AppModule only");
                                          }
                                        }
                                      }
                                
                            

Create FeatureModule - I

  • List of modules
    • Dashboard
      • Hero-search (component)
    • Hero-detail
    • Heroes
    • Messages
      • MessageService

Create FeatureModule - II

                              
                                    import { DashboardComponent } from "./dashboard.component";
                                    import { SharedModule } from "../shared/shared.module";
                                    import { NgModule } from "@angular/core";
                                    import { HeroSearchComponent } from "./hero-search/hero-search.component";
                                    import { DashboardRoutingModule } from "./dashboard-routing.module";
                                    
                                    @NgModule({
                                      imports: [
                                        SharedModule,
                                        DashboardRoutingModule,
                                      ],
                                      declarations: [DashboardComponent, HeroSearchComponent],
                                      providers: [],
                                    })
                                    export class DashboardModule { } 
                            
                        

Create FeatureModule - III

                                  
                                        import { NgModule } from "@angular/core";
                                        import { Routes, RouterModule } from "@angular/router";
                                        import { DashboardComponent } from "./dashboard.component";
                                        
                                        
                                        const routes: Routes = [
                                          {
                                            path: "",
                                            component: DashboardComponent,
                                          },
                                        ];
                                        @NgModule({
                                          imports: [RouterModule.forChild(routes)],
                                          exports: [RouterModule],
                                          providers: [],
                                        })
                                        export class DashboardRoutingModule { }
                                
                            

Create FeatureModule - IV

                                      
                                            import { NgModule } from '@angular/core';
                                            import { RouterModule, Routes } from '@angular/router';
                                            
                                            const routes: Routes = [
                                              { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
                                              { path: 'dashboard', loadChildren: "app/dashboard/dashboard.module#DashboardModule" },
                                              { path: 'detail', loadChildren: "app/hero-detail/hero-detail.module#HeroDetailModule" },
                                              { path: 'heroes', loadChildren: "app/heroes/heroes.module#HeroesModule" },
                                            ];
                                            
                                            @NgModule({
                                              imports: [RouterModule.forRoot(routes)],
                                              exports: [RouterModule]
                                            })
                                            export class AppRoutingModule { }
                                    
                                

Results

Thank You