Best Practices for a Clean and Performant Angular Application

Best Practices for a Clean and Performant Angular Application

 

In this post, we will talk about why you need to clean your code, the best practices for clean and performant Angular applications. We’ll also go through some general coding guidelines to ensure the application is cleaner. 

What is a Clean Code, and Why is it Important?

First, what is clean code? A clean code is a code that is easy to read, understand, change, and maintain. Writing clean code is essential to communicate clearly with the next person who works with what your developers have written. The more declarative code is, the better it is to communicate for what it is made. Moreover, a cleaner code is easier to fix if the issue occurs. When writing code, remember these key principles - Keep It Simple, Stupid (KISS), and Don’t Repeat Yourself (DRY). 

Related read: Step by Step Guide to Hire Angular Developers

Best Practices for a Clean Code & Performant Angular App

Angular App Development

1. trackBy

Use a trackBy function when using ngFor to loop over an array in the template to return a unique identifier for every item. 

With a change in the array, Angular re-renders the entire DOM tree. However, when you are using trackBy, Angular easily understands which element has changed and will modify only those selected DOM elements. 

// in the template

<li *ngFor="let item of items; trackBy: trackByFn">{{item}}</li>

// in the component

trackByFn(index, item) {    

   return item.id; // unique id corresponding to the item

}

2. Const vs. let 

Use const when the value is not reassigned while declaring variables. Using the let and const when needed and apt makes the intention of declaration clear. Also, when a value is reassigned to a constant accidentally by throwing a compile error, it will identify the issues. Besides, the code’s readability is also enhanced. 

// the value of car is not reassigned, so we can make it a const

const car = 'ludicrous car';

let myCar = `My ${car}`;

let yourCar = `Your ${car};

if (iHaveMoreThanOneCar) {

   myCar = `${myCar}s`;

}

if (youHaveMoreThanOneCar) {

   yourCar = `${youCar}s`;

}

3. Pipeable operators 

When using RxJs operators, we use pipeable operators. Pipeable operators are tree-shakeable. By that, we mean that only the code to be executed will be included when imported. You can even identify the unused operators. 

import { map, take } from 'rxjs/operators';

iAmAnObservable

    .pipe(

       map(value => value.item),

       take(1)

     );

4. Segregate API Hacks

We need to add logic to the code to prepare it for the APIs. So, rather than having the hacks in components, it is better to isolate them in one place. For example, you may use a service from the component for the same. It helps keep the hacks closer to the API so that there is minimum code dealing with the un-hacked code. Furthermore, since all hacks are in one place, it is even easier to find them. That is quite helpful when you need to fix bugs. 

5. Subscribe in Template 

It is better to avoid subscribing to observable components. Instead, subscribe using the templates. Async pipes unsubscribe automatically, making code simpler and eliminating the risk of forgetting to unsubscribe a subscription in the component. This generally causes a memory leak. It even stops components from introducing bugs where data is mutated outside the subscription. 

// template

<p></p>

// component

this.textToDisplay$ = iAmAnObservable

    .pipe(

       map(value => value.item)

     );

6. Subscription Cleaning 

Make sure to unsubscribe from them when subscribing to observables. In case you don’t do that, you may lead to unwanted memory leaks as the observable stream is left open. It would be better if you make a lint rule for identifying the observables which are not unsubscribed yet. 

Using takeUntil if you wish to listen to the changes before the value of another observable release. 

private _destroyed$ = new Subject();

public ngOnInit (): void {

    iAmAnObservable

    .pipe(

       map(value => value.item)

      // We want to listen to iAmAnObservable until the component is destroyed,

       takeUntil(this._destroyed$)

     )

    .subscribe(item => this.textToDisplay = item);

}

public ngOnDestroy (): void {

    this._destroyed$.next();

    this._destroyed$.complete();

}

You can easily manage unsubscribing many observable in the component using a private subject like mentioned here. Use take when you just want to emit the first value of the observable. 

iAmAnObservable

    .pipe(

       map(value => value.item),

       take(1),

       takeUntil(this._destroyed$)

    )

    .subscribe(item => this.textToDisplay = item);

Use of take and takeUntil keeps away the memory leaks that can be created when the subscription doesn’t receive the value before the component is destroyed. Otherwise, the subscription would just hang around until it gets its first value. 

Hire Top 1% Angular Developer