Angular Performance Optimization Techniques

Angular is an open source design framework and platform for creating efficient and sophisticated single-page applications.

However, large scale angular applications have some performance issues. We can improve the same by using certain optimization techniques.

Angular Performance Optimization Techniques

1) Change detection strategy

Change detection is used to check whether the application state has been updated and any template needs to be updated. Angular has change detection strategy to check the changes and reflect in application view. Change detection can be triggered either manually or through an asynchronous event.

Default Change Detection 

Change Detection starts by checking the root component, then its children, then its grandchildren, until all the components are checked. It is not a good idea to check all components for every change.

Angular utilizes Zone.js to each asynchronous event, so whenever any event occurs, Angular runs the change detection over its component level.

OnPush Change Detection 

In this strategy, it won't check each component when the change detection runs every time. Angular will check the reference of the objects. Change detection will be run on the OnPush component, only if the inputs reference has been changed.

OnPush change detection strategy saves time and improves performance for the objects.

@Component({

     selector: 'child-component',

     changeDetection: ChangeDetectionStrategy.OnPush,

     template: 'child-component.html'

})

2) Detaching the Change Detector 

Every component in the Angular project tree has a change detector. We can inject the change detector “ChangeDetectorRef” to detach the component from the change detector tree. So, when Angular runs the change detector on the component tree, sub-tree will be skipped.

class SampleComponent {

    constructor(private changeDetectorRef: ChangeDetectorRef) {

        changeDetectorRef.detach()

     }

     clickHandler() {

         changeDetectorRef.detectChanges()

     }

  }

3) Run outside Angular

Angular NgZone is used to trigger async events to run change detection on the component tree.

Zone.js is used to detect when an application state has been changed. It captures asynchronous operations like time-out and network calls and event listeners.

Component({

template: `

<div>

{{data}}

{{done}}

</div>

`})

class SampleComponent {

data = 0

done

constructor(private ngZone: NgZone) {}

insideZone() {

if(data >= 200)

done = "Done"

else

data += 1

}

outsideZone() {

this.ngZone.runOutsideAngular(()=> {

if(data >= 200)

this.ngZone.run(()=> {data = "Done"})

else

data += 1            

})

}

}

insideZone function runs the code and update the UI.

outsideZone function runs the code outside of the ng Zone, so the UI is not updated. We can update the UI to show “Done” when the data is equal or past 200, then re-enter ngZone and set the data to “Done”.

4) Using Pure Pipes

Pipes are used to transform strings, dates and other types of data for display. It’s a simple function to be used in template expressions to accept input and return transformed output. We can use pipes throughout the application.

Two types of pipes are pure and impure. By default, a pipe is Pure.

Only the arguments are dependent upon the pure pipe transform method.

Transform method is called if the reference value it transforms is changed.

Set true value to the pure flag in @Pipe decorator object literal argument.

function convertData(val) {

    return something;

}

@Pipe({

    name: "util",

    pure: true

})

class UtilPipe implements PipeTransform {

    transform(value) {

        return convertData(value)

    }

}

Refer above example, any inputs given to convertData function is computed once and cached, subsequent calls with the same inputs will skip recomputing the convertData function and return the cached results.

5) trackBy option for *ngFor

*ngFor directive is used to repeat the data for each item of the array/collection.

If any new data is added to the array/collection, fetch the data from the server and re-render the DOM. Hence, unnecessarily re-rendering the DOM impacts the performance.

Using Trackby, *ngFor directive can check the object and render only the newly added item.

The function is optionally passed into the ngFor directive to customize how ngFor can uniquely identifies items iteratively.

6) Lazy loading

Lazy loading is used to load components and modules as and when required. It helps to create the initial bundle size smaller and reduce the loading time.

We can split our application modules and load them on-demand. Only after the user selects a route, the modules begin to load.

const routes: Routes = [

  {

path: 'customers',

loadChildren:()=>import('./customers/customers.module').then(m=> m.CustomersModule)

  },

  {

path: 'products',

loadChildren:()=>import('./products/products.module').then(m=> m.ProductsModule)

  },

  {

path: '',

redirectTo: '',

pathMatch: 'full'

  }

];

Preloading 

Preloading is used to load the lazy modules in the background when the user interacts with the application. The user is not required to wait for the module to be downloaded because it's already downloaded in the background. Import PreloadAllModules  from angular/router to enable preloading of lazy loaded modules.

import { PreloadAllModules } from '@angular/router';

RouterModule.forRoot(

  appRoutes,

  {

preloadingStrategy: PreloadAllModules

  }

)

8)Unsubscribe from Observables

Observables are used to transfer events/data between the parts of the application. It is used for event handling, asynchronous programming, and handling multiple values.

A Subscription has an unsubscribe() function to cancel Observable executions.

If a subscription is not closed, then the callback function attached to it will be continuously called. To prevent memory leaks and performance issues, we've to unsubscribe observables.

Every component can be unsubscribed from the observables using the OnDestroy lifecycle hook. So when we leave the component, all the used observables are unsubscribed.

ngOnDestroy() {

        this.subscriptionRef.unsubscribe(); // Unsubscribe Observable  

  }

Conclusion

In this article, we discussed how change detection, lazy loading, and trackby helped us achieve great performance in angular applications.

The performance and the load time of any application play important role in saving time and effort for the users. So, it is essential to adopt some optimization techniques that can improve the application's performance.

 

If you are looking for Angular developers to develop Angular application or to improve your app performance, you are at the right place.

Infinijith provides you app development experts as per your needs. Hire Angular developers now to have a powerful application for your business.

 

 

 

Recommended Articles:

1) Reactive Programming in Angular

2) Advantages and Disadvantages of Angular

3) Angular vs React

Gnanasampath

Gnanasampath

Senior Full stack developer

Comments