How to get the best performance out of your Angular apps

<strong>Angular is a great framework and can be used for developing large scale applications, but can be tricky to fine tune and achieve good load time and run-time performance. In this post, I’ll detail some best practices I have learned along the way, so you will not make the same mistakes I made.</strong>

Angular is a great framework and can be used for developing large scale applications, but can be tricky to fine tune and achieve good load time and run-time performance. In this post, I’ll detail some best practices I have learned along the way, so you will not make the same mistakes I made.

Change detection

Change detection is Angular’s mechanism to see if there are any values that have been changed and require the view to be updated. By default, Angular runs change detection with nearly every user interaction. In order to know if the view should be rendered again, Angular accesses the new updated value, compares it with the old one and makes the decision. As your application grows, it will include a lot of expressions, and having a change detection cycle on each one of them will cause a performance problem.

We can optimize things if we create a ‘dumb’ component with a certain attribute to handle the change detection cycles. This component relies only on non specific input data and in that way, we can tell Angular only to run change detection when an input changes or when we manually trigger it. When a reference type is immutable, every time the object is being updated, the reference on the stack memory will have to change. Now we can have a simple reference check on the object between the memory address and the stack. If the memory address has changed, then we check all the values. This will skip change detection in that component.

We need to keep in mind that primitive types such as numbers, booleans, strings, etc are passed by value. Objects, arrays and functions are also passed by value, but the value is a copy of a reference.

You can look for more details on that here.

And now we will see two examples of how this is implemented.

Example: ChangeDetectionStrategy.Default

You don’t have to specify changeDetection type, it will be ‘ChangeDetectionStrategy.Default’ by default.

@Component({
  selector: 'app',
  template: `
  <person-details [person]="person"></person-details>
  <button type="button" (click)="changeProperties()">
      Change Properties
  </button>
  <button type="button" (click)="changeObject()">
      Change Object
  </button>
  `
})

export class AppComponent {
person: Person = new Person('John', 'Lennon');

changeProperties(): void {
this.person.firstName = 'George';
this.person.lastName = 'Harrison';
}

changeObject(): void {
this.person = new Person('Paul', 'McCartney');
}
}
export class Person {
constructor(public firstName: string, public lastName: string) { }
}
@Component({
selector: 'person-details',
template: &lt;p&gt; &lt;label&gt;Person: &lt;/label&gt; &lt;span&gt;{{person.firstName}} {{person.lastName}}&lt;/span&gt; &lt;/p&gt;,
})

export class PersonDetailsComponent {
@Input() person: Person;
}

ChangeDetectionStrategy.OnPush

In order to use the OnPush change detection, we need to modify the child component from the first example.

import { Component, Input, ChangeDetectionStrategy} from '@angular/core';
import {Person} from '../models/person';
@Component({
selector: 'person-details',
templateUrl: './personDetails.component.html',
styleUrls: [ './personDetails.component.css' ],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PersonDetailsComponent {
@Input() person: Person;
}

Minimize DOM manipulations

If you have some list of data that was retrieved from some server and you need to show it, you are probably using the Angular directive, ngFor. Angular will create a new template for you for each item in that list.

If at some point some of the data has been changed, Angular can’t really know that and will replace the whole list, instead of just the items that were changed. In order to improve that, Angular provide us with the trackByfunction.trackBy takes a function which has two arguments: index and [item](https://angular.io/api/core/IterableChangeRecord#item). If trackBy is given, Angular tracks changes by the return value of the function.

Syntax:

<li *ngFor="let item of items; index as i; trackBy: trackByFn">...</li>

Most common use is just to return the index itself or item.id as a unique identifier for the item: trackByFn(index, item){ return item.id; }.

With that, Angular can track which items have been added or removed according to the unique identifier and create or destroy only the things that were changed.

Avoid using methods in your template

While it is very convenient to use methods in Angular templates, Angular will recalculate them on each change detection. For larger lists it will affect rendering time and the application may even get stuck due to huge memory consumption. In the following example, Angular will run getNumberOfCars on each change detection cycle (ie upon adding a new row).

How can we handle this situation? We can pre-compute the results and then just access the data we have computed. In our example, we can add a new attribute to the person object, vehiclesNumber, which holds in advance the amount of vehicles each person has. The other way to do this is by implementing the method getNumberOfCars as a pure pipe.

According to Angular pipe documentation:

Angular executes a pure pipe only when it detects a pure change to the input value. A pure change is either a change to a primitive input value (StringNumberBooleanSymbol) or a changed object reference (DateArrayFunctionObject).
Angular ignores changes within (composite) objects.
This may seem restrictive but it’s also fast. An object reference check is fast — much faster than a deep check for differences — so Angular can quickly determine if it can skip both the pipe execution and a view update.

The pipe will still be executed on each change detection cycle. However, if a pipe is executed more than once with the same parameters, the results of the first execution are returned. Meaning, Angular will cache the results for better performance.

Let’s see an example.

Without a pipe:

import { Component } from '@angular/core';
import { Person } from '../models/person';
@Component({
selector: 'my-app',
template: &lt;button (click)="addPerson()"&gt;add person&lt;/button&gt; &lt;ul&gt; &lt;li *ngFor="let person of personsList"&gt; &lt;span&gt; Name: {{person.firstName}} {{person.lastName}},&lt;/span&gt; &lt;span&gt; Number of cars: {{getNumberOfCars(person)}}&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt;
})
export class AppComponent {
personsList: Person[] = [
{
firstName: 'John',
lastName: 'Lennon',
vehicles: ['Austin maxi', '1979 Mercedes-Benz 300TD Wagon', '1965 Rolls-Royce Phantom V', '1956 Bentley S1']
},
{
firstName: 'George',
lastName: 'Harisson',
vehicles: ['McLaren F1', 'Mini Cooper S', 'Ford Anglia']
}
];

addPerson(): void {
const person: Person = {
firstName: 'Paul',
lastName: 'McCartney',
vehicles: ['Radford Mini Cooper S', 'Lamborghini 400GT', 'Austin Healy']
}
this.personsList.push(person)
}
getNumberOfCars(person: Person): number {
console.log("calculating number of cars")
return person.vehicles.length;
}
}

While with a pipe we will get:

@Pipe({ name: 'carsCounter' })
export class CarsCounter implements PipeTransform {
transform(person: Person) {
console.log("transforming..")
return person.vehicles.length;
}
}
@Component({
selector: 'my-app',
template: &lt;button (click)="addPerson()"&gt;add person&lt;/button&gt; &lt;ul&gt; &lt;li *ngFor="let person of personsList"&gt; &lt;span&gt; Name: {{person.firstName}} {{person.lastName}},&lt;/span&gt; &lt;span&gt; Number of cars: {{person | carsCounter}}&lt;/span&gt; &lt;/li&gt; &lt;/ul&gt;
})

We can see it will recalculate only on the new data, instead of the whole list.

Use Prod flag in production

It will disable Angular’s development mode, which turns off assertions and other checks within the framework. This will also increase your performance. You can find more details here.

Don’t use console.log in production code

console.log prints can really slow down your application, as it takes some time to compute what you want to print. Also, for long information it will also consume some more time for the printing process.

Don’t forget to unsubscribe from your observables

Your subscription holds a reference to your component instance. If you will not unsubscribe from it, the instance will not be cleared by the garbage collector which will cause a memory leak. You can unsubscribe easily by using ngOnDestory(){this.subscription.unsubscribe();}. You can read more about it here.

Final Words

If you run into any issues, feel free to drop me a line at : markgrichanik[at]gmail[dot]com.

I would also love to hear any feedback/tips you have while working on large scale applications with Angular.

Originally published by Mark Grichanik at https://medium.freecodecamp.org

Learn more

☞ Angular 7 (formerly Angular 2) - The Complete Guide

☞ The Complete Angular Course: Beginner to Advanced

☞ NativeScript + Angular: Build Native iOS, Android & Web Apps

☞ Ionic 4 Crash Course with Heartstone API & Angular

☞ Angular 6 , Angular 7 Step by Step for beginners

☞ NgRx In Depth (Angular 7 and NgRx 7, with FREE E-Book)

☞ Learn Protractor(Angular Automation) from scratch +Framework

ECommerce Mobile App Development | Ecommerce Mobile App Development Services

We are leading ecommerce mobile application development company. Hire our ecommerce mobile app developer for your custom Ecommerce project at competitive rates. **Know about [Top ECommerce Mobile App Development...

We are leading ecommerce mobile application development company. Hire our ecommerce mobile app developer for your custom Ecommerce project at competitive rates.

Know about Top ECommerce Mobile App Development Company

ECommerce Mobile App Development Company in England

ECommerce Mobile App Development Company in England

At [**WebClues Global**](https://www.webcluesglobal.com/ "WebClues Global") we have been working on eCommerce apps for the last 7+ years and have built systems which are secure, reliable and easy to use. We have people who have good knowledge on a...

At WebClues Global we have been working on eCommerce apps for the last 7+ years and have built systems which are secure, reliable and easy to use. We have people who have good knowledge on a wide variety of ecommerce technologies – Magento eCommerce, WooCommerce, Shopify, Drupal Commerce, OpenCart, BigCommerce, Joomla , Prestashop, NopCommerce.

As a top ECommerce Mobile App Development Company in England, We have been in the business of software develop ment for 7+ years and we are a specialist in Team Software Development by following Agile Methods. We provide a range of services on eCommerce app development with the support of our deep web application development and mobile app development expertise.

Mobile App Development Company in USA

Mobile App Development Company in USA

**How [Mobile App Development Company in the USA](https://www.dataeximit.com/mobile-app-development-service/ "Mobile App Development Company in the USA"), can breathe life into Your Amazing Ideas?** Today’s Mobile world mobile apps become one of...

How Mobile App Development Company in the USA, can breathe life into Your Amazing Ideas?

Today’s Mobile world mobile apps become one of the important factors in each and every business whether it may be a product based company or a service-based company.

Data EximIT has a strong team of mobile app developers & programmers who have the qualifications and experience in developing apps across several platforms, including iOS, Android, and PhoneGap and. We give our clients complete flexibility with respect to cutting short or extending projects after the minimum term is complete.

Our Mobile App Development Services Are...

  • Android Application Development
  • iOS Application Development
  • Responsive Web Applications
  • Hybrid Mobile Application Development
  • Xamarin Application Development
  • Mobile UI/UX Design

Contact Our Experts For More Information