Optimized Angular apps:

  • smaller

  • faster

  • better

Web App Performance

Network bandwidth

Device performance

}

}

Generate smaller bundles

Optimize the code to display UI updates faster

Network performance strategy

  • Make overall bundle size smaller

  • Split bundle and download only what we need for the starting-up

  • Cache network responses for the future usage

Build the app using prod

$ ng build --prod
  • Using Ahead of Time compilation

  • Using Build Optimizer

  • Registering Angular Service Worker (if enabled)

  • Executes enableProdMode() via setting prod environment

Recipe #1

How to

$ ng build --prod --source-map
$ npx source-map-explorer main.bundle.js

Use lazy loading

  • Download the only code needed to start the app

  • Use CanLoad guard to mediate navigation

  • Preload all the modules (except the ones protected by CanLoad) by using PreloadAllModules strategy

  • 100% flexibility with your custom PreloadingStrategy

Recipe #2

How to

const appRoutes: Routes = [{
  path: 'tweets',
  loadChildren: 'tweets/tweets.module#TweetsModule'
}]
const tweetsRoutes: Routes = [{
  path: '',
  component: TweetFeedsComponent
}];

app-routing.module.ts

tweets/tweets-routing.module.ts

Preloading strategy

@NgModule({
  imports: [RouterModule.forRoot(appRoutes, {
    preloadingStrategy: PreloadAllModules
  })],
  exports: [RouterModule]
})

app-routing.module.ts

Consider server-side rendering

  • Better first-load experience

  • Social links with previews of a web site

  • Better for SEO

Recipe #4

Bootstrap

Load HTML

First meaningful paint

Bootstrap

Load HTML

First meaningful paint

No SSR

SSR

<app-root>Loading</app-root>

Loading

How to

A short way

A long way

$ ng add @ng-toolkit/universal
$ npm run build:prod
$ npm run server
$ ng generate universal --client-project=ssr

...and follow the guide at https://angular.io/guide/universal

Angular change detection (CD)

Data bindings

Update DOM

Event handlers

}

Change detection

}

UI render

Trigger

Ready

}

60FPS / 17ms

Code performance strategy

  • Make each change detection faster

  • Reduce number of change detections

  • Render as few as possible DOM changes

Use pure pipes instead of methods

<span>{{ relativeDate(tweet.createdAt) }}</span>

Calculated on every change detection

Recipe #5

<span>{{ tweet.createdAt | relativeDate }}</span>

Calculated only if the value was changed

Use OnPush CD strategy

Recipe #6

  • Every time

  • Any event happens

  • All components

}

By default

Use OnPush CD strategy

Recipe #6

  • Every time

  • Any event happens

  • All components

}

By default

Use OnPush CD strategy

Recipe #6

  • Every time

  • Any event happens

  • All components

}

By default

Use OnPush CD strategy

Recipe #6

  • Every time

  • Any event happens

  • All components

}

By default

How to

import { ..., ChangeDetectionStrategy } from '@angular/core';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})
  • The @Input reference changes

  • An event occurres from the component or one of its children

  • Running change detection explicitly

  • Observable linked to the template via the async pipe emits a new value

ChangeDetectionStrategy.OnPush

Go for your own CD schedule

  • Disabling CD for the component completely

  • Running some code outside Angular CD

Recipe #7

How to

import { ..., ChangeDetectorRef } from '@angular/core';

class RealTimeList {
  constructor(private ref: ChangeDetectorRef) {
    ref.detach();
    setInterval(() => {
      this.ref.detectChanges();
    }, 1000);
  }
}
  • detach() / reattach()

  • detectChanges() / tick() / markForCheck()

How to

import { ..., NgZone } from '@angular/core';

class MyComponent implements OnChanges {

  constructor(private _ngZone: NgZone ) {}

  log() {
    this._ngZone.runOutsideAngular(() => {
      // Any code will not cause CD
    }}));
  }
}

Use trackBy in ngFor loops

  • DOM manipulations are expensive

  • Immutable practices generate a new DOM collection

Recipe #8

How to

export class TweetListComponent implements OnInit {
  ...

  trackById(index, tweet) {
      return tweet.id;
  }
}
<div *ngFor="let tweet of tweets; trackBy: trackById">

Angular App Performance

Networking

Code execution

}

}

  • Production mode

  • Lazy loading

  • Service worker

  • Server-side rendering

  • Using pure pipes

  • OnPush CD strategy

  • Custom CD strategy

  • Using trackBy

Thank you!

Questions?

Angular 5 Advance webinars 07

By Tarun Sharma

Angular 5 Advance webinars 07

Angular apps are getting more performant with each new version of the framework - thanks to the huge number of internal optimizations. But the main responsibility for the eventual app performance is on us, developers. Let's go through the main points on how we could help the framework to build and the browser to perform our app better.

  • 723