I hope you have read Part 1 of this blog series, if not, you can read it here. In this part, I’m going to walk you through methods to optimize the Run performance in Angular.
Explore the remarkable impact of our Angular UI test automation solution, reducing manual testing efforts by 90% for a client.
Let’s dive in!
Methods to optimize the Run performance
Angular Change Detection Strategies
When the data changes, the process of updating the view (DOM). Change detection does not check a deep object comparison. Instead, it compares the previous and current values of the template’s properties.
Angular provides two methods for running change detections:
Default Change Detection Strategy
Angular by default uses the Change Detection Strategy. Default strategy. This default strategy checks every component in the component tree from top to bottom every time when an event trigger (like user event, timer, XHR, promise and so on). It will take time to detect changes and re-render the view.
If your app has a lot of data with a lot of asynchronous events, it will have a negative impact on performance.
Fig 1: Default Change Detection Strategy
Source: https://www.dotnettricks.com
OnPush Change Detection Strategy
This change detection strategy provides the possibility to skip unnecessary checks for this component and all its child components.
We can switch to the Change Detection Strategy. OnPush change detection strategy by adding the changeDetection property to the component decorator metadata:
Fig 2: OnPush Change Detection Strategy
Fig 3: OnPush Change Detection Strategy
Fig 4: OnPush Change Detection Strategy
https://www.dotnettricks.com /learn/angular/tips-to-optimize-your-angular-application
Angular knows that the component only needs to be updated if the following conditions are met:
- The input reference has changed.
- The component or one of its children components triggers an event handler.
- Change detection is triggered manually.
- An observable linked to the template through the async pipe emits a new value.
Optimize template expressions
Methods in a template will get triggered each time a component is rerendered. A simple template binding that executes empPercentage() for each entry in employeeList on every change detection cycle.
Fig 5: Optimize template expressions
If there is a complex business inside the method, then the template rendering will take time, and the performance will degrade. You can use pipe instead of methods in a template.
Using pipes instead of methods in templates
Pipes are used to format data and make it more readable.
Fig 6: Using pipes instead of methods in templates
Fig 7: Using pipes instead of methods in templates
Pipes are divided into two categories: –
- Impure pipe – An impure pipe run change detection cycles on every change, so they do not perform well.
- Pure Pipe – When true, the pipe is pure, meaning that the transform() method is invoked only when its input arguments change. Pipes are pure by default.
Fig 8: Using pipes instead of methods in templates
Web Workers
JavaScript is a single-threaded language with a main thread that runs in the browser. If our application performs heavy tasks on startup, such as complex calculations or graph rendering, the UI may freeze, and the user may become frustrated with the application.
Web workers are the solution to this problem. Web workers start a new thread that runs in parallel with the main UI thread. Web workers are intended to perform CPU-intensive tasks, such as complex calculations or data processing, without interfering the main UI thread and rendering the application unresponsive.
Fig 9: Web Workers
https://medium.com
Fig 10: Web Workers
Fig 11: Web Workers
In this example, the web worker uses the postMessage method to calculate the sum of an array of numbers and returns the result to the main thread. When a message event occurs, the Angular component listens for it and updates the result property with the returned value.
*ngFor
*ngFor structural directive adds and removes DOM elements to loop over data and manipulate the DOM. Angular creates a new instance of the template for each item in the array. When the array is large or the items are frequently updated, this can cause performance issues.
Use the trackBy function to identify unique items and only update the template for those that have changed.
Fig 12: ngFor
ngDoCheck
ngDoCheck is a lifecycle hook in Angular that is called every time the change detection is triggered for the component and its children. If you are using this function for any computational task, your app will be slowed down. Thus, you must keep a check on what and how you use this function.
Global Variables
Memory leakage is one of the drawbacks of using global variables. The global scope variables will not be cleared until the window or tab is reloaded. In the programme, instead of using global variables throughout the file, use local variables (let,const).
Event listeners
Adding event listeners to your DOM node may result in a memory leak. If you forget to remove the listener from your directive’s ngOnDestroy() hook, it will retain a reference to a DOM node even if it is removed from the document. The DOM tree will then be converted to a “Detached DOM tree” and leak.
Replace show/hide with ngIf
Hiding and showing the element after rendering is OK in case the paragraph or div element is tiny and with simple interaction. However, with Angular, we can build rich applications. Some of the components may use too many resources. And even though the component is hidden, it will be attached to its DOM element. It will keep on listening for events.
So, it’s better to add or remove elements to the component element to the HTML DOM rather than hiding or showing them, which can improve performance.
However, if the component is simple, you should hide or show it, since component reinitialization operation can be expensive.
The difference between the find() and filter() methods
Fig 13: The difference between the find() and filter() methods
The main advantage of using find() in those cases is that find returns as soon as a match is found, but filter() would run through the entire array even if a match is found in the 1’st index position and you should not do that for big arrays when one match is important to you!
ngOnDestroy()
ngOnDestroy() is an Angular lifecycle hook that is invoked just before the component is destroyed and removed from the DOM. It provides a method for cleaning up any resources acquired by the component during its lifetime, such as subscriptions, timers, or other types of memory or resource allocation.
Console.log()
Using console.log() statements in production code may not be a good idea as it will slow down the app performance and logging objects with console.log() leads to a memory leak. When the browser’s console window is open, the console.log() execution is slowed even more, negatively impacting the site’s performance. It’s better to completely remove the console.log() statements from your production code.
Let me wrap up my thoughts…
The performance and the load time plays an essential and important role for any application which in turn is linked with business benefits. This blog series covered a few aspects on how we can make use of the right compilation methods and techniques that can improve the application performance.
We explored the process of change detection, lazy loading, and web workers. These can guide us to achieve stellar performance. Before you use any of these techniques, you should first figure out the reason behind the lagging performance. So, the right approach will help us to hit the bull’s eye.
Hope you enjoyed this series! 😊 Happy reading. Reach out to us with your thoughts about this blog! Also visit us at Nitor Infotech to know more about us!