Tips to Optimize Your Angular App Performance

Wednesday, March 20, 2024

Every application user expects better performance along with faster loading to get a seamless experience. And this is only possible when developers optimize the application efficiently to boost performance. To offer such optimized high-performance applications, Angular is used. Every Angular development company follows some unique techniques in the development process that enhance application performance. To know more about these techniques and see how one can improve the performance of the Angular application, let’s go through this blog where we will discuss some tips to optimize Angular performance.

1. Effective Tips to Optimize Angular Applications

Angular is a framework that offers the best performance for the large-scale application. Generally, developers have to keep a lot of factors in mind while working with complex applications, but with Angular, one can get a set of techniques and methods that can be followed to get the most efficient and optimized Angular application for any size of business. Some of these essential and effective tips to mitigate major performance issues are discussed here for a developer to significantly alleviate the performance optimization of an Angular application.

1.1 Use Change Detection Strategy

The very first tip for optimizing the Angular application performance is to use a change detection strategy. Change detection strategy enables Angular developers to monitor changes in the Angular app and reflect time in user data within component data. And when applications trigger change detection frequently, they can impact the performance. To avoid performance damage, the following change detection strategies must be considered:

OnPush Change Detection Strategy

Angular comes with a default setting that checks for changes like root component and smallest subtree. This can sometimes be inefficient. In this case, with the help of the OnPush change detection strategy, a developer can streamline this issue and make the application focus only on the branches that require change detection and not check the unnecessary root components and branches. For this, the following code can be used:

@Component({
   selector: 'app-root',
   template: `Number of ticks: {{numberOfTicks}}`,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
 
class AppComponent {
  numberOfTicks = 0;
 
  constructor(private ref: ChangeDetectorRef) {
setInterval(() => {
   this.numberOfTicks++;
   // require view to be updated
   	this.ref.markForCheck();
}, 1000);
  }

Detach Change Detector

Another default change detection strategy is to detach the change detector itself from the Angular application. The main reason behind this is that, in Angular, every component is connected with a change detector. And when any application has numerous components, rendering them takes a prolonged time. To resolve this issue, the developer needs to detach the change detector from the selected components. Here is the code for the same.

abstract class ChangeDetectorRef {
abstract markForCheck(): void
abstract detach(): void
abstract detectChanges(): void
abstract checkNoChanges(): void
abstract reattach(): void 
}

Using Pure Pipes

Using pure pipes is another strategy to use change detection in Angular to optimize & improve the performance of the application. Generally, in Angular, pipes transform the input values of the angular app within the expressions of the template. In this case, there are two categories: pure and impure. As the name suggests, pure pipes are the category that offers consistent output for identical inputs. Impure pipes offer different results. This is why, by default, Angular uses pure pipes.

 Angular pure pipes make sure that trigger change detection only occurs when there is an actual change in the input value. For this, the following code can be used:

@Pipe({
   name: 'filterPipe',
   pure: true  
}) 
export class FilterPipe {}

1.2 Lazy Loading

Another tip for Angular performance optimization is lazy loading. Angular lazy loading is a process that is specially designed to hold the initializing of an item until it is required. It can be used by the developers to improve the performance of the application by reducing the resources and time that go into initializing and loading objects that are not going to be used. In this case, the lazy loading approach can be used to lessen the main bundle size of the Angular application. Here are the strategies to carry out his tip:

Lazy Loading Modules

The very first strategy is to modularize the application and plan the routes for lazy loading. Here we will have a look at an example where there are three lazy load modules and routes. Then lazy loading can be implemented for the clients and order components. Here is the code for the same.

import { NgModule } from '@angular/core';
 import { Routes, RouterModule } from '@angular/router';
 import { PageNotFound } from './page-not-found/page-not-found.component';
 import { CustomPreloadingService } from './shared/custom-preloading.service';

 const routes: Routes = [
  {
	path: '',
	redirectTo: 'dashboard',	
	pathMatch: 'full',
  },
  {
	path: 'dashboard',
	loadChildren: () =>
  	import('./dashboard/dashboard .module').then((m) => m.DashboardModule),
  },
  {
	path: 'orders',
	loadChildren: () =>
  	import('./orders/orders.module').then((m) => m.OrdersModule),
  },
  {
	path: '**',
	component: PageNotFound,
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [],
})
export class AppRoutingModule {}

Lazy Loading Images

Another strategy is loading images when required which means when they are in the viewport.  This approach can help developers to optimize the application’s performance & poor user experience by reducing the initial load time. For this, the Angular developer has to implement Native lazy loading, as shown in the below command line:


Here, there are three loading attributes namely lazy, eager, and auto. They all have their purposes to serve. The lazy loading attribute that we have used in the above command asks the web browser not to load the resource until it enters the viewport. But when this command runs on the browser, the implementation gets affected. To handle this, a placeholder image must be used as a default image until the loading of the actual image is processed. For this, the following code snippet must be followed:


1.3 Use Angular Universal for Server-side Rendering

Using Angular Universal for server-side rendering is another Angular performance optimization tip. It is known to us that by lazily loading the application, one can save the time a web page takes to load because of its size. In this case, when a server-side rendering process is used, it can significantly improve the web page load time. Normally it happens that any application in Angular gets executed directly in the browser and then the DOM gets its update when the events in the application are triggered.

But here, when the development team uses Angular Universal, an application generates a static app in the web server and helps in reducing the load time. Besides this, Angular server-side rendering also helps in improving the SEO performance optimization of an application.

1.4 Use AOT Compilation

Another Angular performance optimization tip is to use the Ahead Of Time(AOT) compilation. It helps in converting Angular HTML and TypeScript code. It makes the code more efficient and turns JavaScript code into a better-performing app. 

AOT compiler enables the compiling of Angular applications and libraries during the build time. It also helps in extracting the metadata which can specify the modules that need to be managed. The three phases of AOT compilation are:

  • Phase I: This phase represents code analysis. Here the TypeScript compiler and AOT collector both generate a representation of the source code.
  • Phase II: Here the code is generated where the AOT compiler’s StaticReflector specifies the metadata of the previous phase.
  • Phase III: It checks the template of the application.

1.5 Usage of Web Workers

Using web workers is another popular tip for performance tuning of an angular app. When the computation is heavy in any large-scale application, web workers can be adopted as they are specially designed to execute heavy computations. For using web workers, developers need to set up and coordinate the applications as here they will have to manage communications of multiple threads. For this, the following code can be used:

// my-worker.ts

// Define a function that will be executed in the web worker
function doHeavyComputation(input: number): number {
  // Perform some heavy computation here
  return input * input;
}

// Set up a message listener to receive messages from the main thread
addEventListener('message', event => {
  // When a message is received, extract the data from the event
  const data = event.data;

  // Call the function and return the result to the main thread
  const result = doHeavyComputation(data.input);
  postMessage(result);
});
// my-component.component.ts
@Component({
  selector: 'app-my-component',
  template: `Result: {{ result }}`
})
export class MyComponent {
  result: number;

  constructor() {
    // Create a new instance of the Worker class
    const worker = new Worker('./my-worker.ts', { type: 'module' });

    // Set up a message listener to receive messages from the web worker
    worker.addEventListener('message', event => {
      // When a message is received, extract the data 
      // from the event and update the component state
      const data = event.data;
      this.result = data;
    });

    // Send a message to the web worker
    worker.postMessage({ input: 5 });
  }
}

1.6 Use TrackBy Option

When it comes to rendering huge lists with attached listeners, the performance of the application is affected. This can cause scroll jank and when the lists need to be updated, adding or removing an item from a long list can also affect the performance.

In order to resolve this issue and help Angular handle the list, the developer needs to offer a unique reference for each item that is present in the list with the use of the trackBy function. Here is an example of the same:

@Component({
   selector: 'the-fruits',
   template: `
 	
  • {{ fruit.name }}
`, }) export class FruitsComponent { fruits = [ { id: 1, name: 'Raspberry' }, { id: 2, name: 'Apple' }, { id: 3, name: 'Pome' }, { id: 4, name: 'Mango' } ]; addFruit() { this.fruits = [ ...this.fruits, { id: 5, name: 'Strawberry' } ]; } trackByFunction(index: number, item: any): number { return item.id; // or unique identifier for your items } }

1.7 Optimize HTTP Requests

The last tip in our list to optimize the Angular application performance is optimizing HTTP requests. These are the requests that are known as a common bottleneck. In order to optimize the app’s performance, one has to make sure that the app minimizes the HTTP request numbers and uses the correct caching mechanisms. For this, the best way is to optimize the HTTP request. For this, the developer can use the HttpClient module in Angular as shown in the below code:

import { Component } from '@angular/core';

 import { HttpClient } from '@angular/common/http';

 @Component({

   selector: 'app-my-component',

   templateUrl: './my-component.component.html',

   styleUrls: ['./my-component.component.css']

 })

 export class MyComponent {

  baseUrl = '/api';
   constructor(private http: HttpClient) {}

   getData(path: string, params?: any): Observable {
	return this.httpClient.get(this.baseUrl + '/' + path, {
  	params,
	});
 }

}

2. Conclusion

As seen in the above blog, when Angular app development companies make use of efficient optimization techniques for resolving any type of issue in the application, the smooth user experience & performance of the Angular app will be noticed. Here we discussed some of such tips that can be used to optimize the application and produce better results.

Comments


Your comment is awaiting moderation.