Angular RTP Meetup
Hey, Am Udhay (OO-dhy)
Module
Components
Pipes
Directives
Root / Main
Home
Products
Cart
Payment
Orders
Root / Main
Home
Products
Cart
Payment
Orders
/home
/products
/cart
/billing
/orders
https://someonlinestore.com/
Create new Angular project
ng new someonlinestore --routing
ng generate module payment --route billing --module app.module
Create feature module (Angular takes care of lazy loading configuraiton)
Application's Root Module Routes look like:
const routes: Routes = [
{
path: 'billing',
loadChildren: () =>
import('./payment/payment.module').
then((m) => m.PaymentModule),
}
];
When User accesses https://someonlinestore.com/billing, Payment module gets loaded and their content painted on UI
This can be fixed by Preloading the module that's huge in size based on different strategies. Let's dig into it more..
Preload All Modules by setting preloadingStrategy router option as below:
@NgModule({
imports: [
RouterModule.forRoot(routes,
{ preloadingStrategy: PreloadAllModules }
),
],
exports: [RouterModule],
})
Set Preload JSON parameter value to either true or false in the route. And update preloadingStrategy to SelectivePreloadStrategy (let's create it).
const routes: Routes = [
{
path: 'home',
loadChildren: () => import('./home/home.module').then((m) => m.HomeModule),
data: {preload: true}
},
{
path: 'about',
loadChildren: () =>
import('./about/about.module').then((m) => m.AboutModule),
data: {preload: false}
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, {preloadingStrategy: SelectivePreloadStrategy}),
],
exports: [RouterModule],
})
Create a Service class 'SelectivePreloadStrategy' & implement PreloadingStrategy Interface. Add logic within preload method that decides whether to preload module or not..
import { Injectable } from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable, EMPTY } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SelectivePreloadStrategy implements PreloadingStrategy{
constructor() { }
preload(route: Route, load: () => Observable<any>): Observable<any>{
return route.data && route.data['preload'] ? load() : EMPTY;
}
}
const routes: Routes = [
{
path: 'home',
loadChildren: () => import('./home/home.module').then((m) => m.HomeModule),
data: {preload: true}
},
{
path: 'about',
loadChildren: () =>
import('./about/about.module').then((m) => m.AboutModule),
data: {preload: false}
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, {preloadingStrategy: NetworkPreloadStrategy}),
],
exports: [RouterModule],
})
Update preloadingStrategy to NetworkPreloadStrategy (let's create it).
import { Injectable } from '@angular/core';
import { PreloadingStrategy } from '@angular/router';
import { EMPTY, TimeoutError } from 'rxjs';
export declare var navigator;
@Injectable({
providedIn: 'root'
})
export class NetworkPreloadStrategy implements PreloadingStrategy{
constructor() { }
preload(route: import("@angular/router").Route, load: () => import("rxjs").Observable<any>): import("rxjs").Observable<any> {
return this.hasGoodNetworkConn() ? load() : EMPTY;
}
hasGoodNetworkConn() {
const conn = navigator.connection;
if(conn){
const connectionsToAvoid = ['2g', '3g'];
const connectionType = conn.effectiveType || '';
console.log(connectionType);
if(connectionsToAvoid.includes(connectionType)){
return false;
}
}
return true;
}
}
Decide preloading based on Network..
const routes: Routes = [
{
path: 'home',
loadChildren: () => import('./home/home.module').then((m) => m.HomeModule),
data: {preload: true}
},
{
path: 'about',
loadChildren: () =>
import('./about/about.module').then((m) => m.AboutModule),
data: {preload: false}
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, {preloadingStrategy: QuickLinkStrategy}),
],
exports: [RouterModule],
})
Using ngx-quicklink, the configuration is straightforward..
Import the QuicklinkModule in AppModule and add QuickLinkStrategy as Preloading strategy
Twitter- https://twitter.com/AskUdhay
Check my previous talks - http://askudhay.com/