Building Performance First Angular Apps - Part 2

Saturday 22nd of August 3:00 PM
Vicentiu B.

If you liked my tips on Angular Performance in HTML templates, this week we can dig in some more tips.
This time, we're looking at how to fine tune the architecture to get the most out of Angular in terms of performance.

Unsubscribe observables

export class AppComponent implements OnInit, OnDestroy {
  users = [];
  subs = new Subscription();
  constructor(private userService: UserService){ }
  ngOnInit() {
    this.subs.add(  
    this.userService.users$.subscribe(newUsers => this.users = newUsers)     );}
  ngOnDestroy() {
    this.subs.unsubscribe();
 }}

 

Avoid sending heavily updated objects through input

In the example below, we're sending the users array through @Input. But to receive updates to the array, we need to implement ngOnChanges which is also triggered for any other input change.

Instead, you can use Observables to notify when the array has changed and send the new value.

<app-hello [users]="users"></app-hello>

--------------------------------------------------

export class HelloComponent implements OnChanges {
  @Input() users: string;D
  ngOnChanges(changes: SimpleChanges) {
    this.users = changes.users.currentValue;
  }
}

 

Use debounce and switchMap to avoid unnecessary requests

In the code below, we're delaying/debouncing the request with 500ms and using switchMap to cancel any pending request but the latest one. Check out the working code here.

    this.searchText$.pipe(
      debounceTime(500),
      distinctUntilChanged(),
      switchMap(movName => this.searchService.search(movName))      
    );

 

Use Lazy Loading

const routes: Routes = [{ 
    path: 'items', 
    loadChildren: () => import('./items/items.module')
                .then(m => m.ItemsModule) 
}];

Lazy Loading for Modules (as seen above) - click here to read more
Lazy Loading for Components - click here to read more
 

Make use of Singleton Services

Singleton Services come by default in Angular, and having one instance in the whole app can benefit in some cases. You can cache some data or have subjects to which other components subscribe. Read more on Singleton Services

export class SearchService {
  private cachedData = [];
  constructor(private http$: HttpClient) {}
  …
}

 

Fetch data at the highest level available

When the same piece of data is needed in multiple components, you can fetch it at a higher level (a service) and send the updates through a Subject.
 

Adjust Change Detection

Angular is eager to run the change detection on each change in the application. However this might not be the best approach performance-wise.

You can look into switching the Change Detection Strategy to On-Push. With On-Push, Angular will trigger change detection on component inputs, events from the component or its children, by using async pipe or by triggering change detection explicitly. You'll also have to refrain from mutating objects directly.

A great example is explained on Angular University.
 

Use Ivy

Make use of the new Ivy engine. Enabled by default in Angular 9+. Read more here
 

Speed up Unit Tests

If you're using Ivy, you're set, the Ivy engine comes with caching for TestBed components.

However, if you're stuck with an older version of Angular, take a look at ng-bullet.

These tips & tricks don't represent an exhaustive list, and other improvements are definitely out there. Let's chat on Twitter about these & other tips on Angular performance.

Vicentiu B.  

Passionate full-stack developer with an eye for User Interface and flashy new web features