Join us at GITEX 2024! Discover our solutions at Hall 4, Booth H-30 Schedule a Meeting Today.
Automate Marketing Initiatives with Salesforce Marketing Cloud Learn More
Join us at GITEX 2024! Discover our solutions at Hall 4, Booth H-30 Book your live demo today.

7 Tips To Boost Your Angular Application Performance

Angular is a robust Javascript framework, and by default, it provides superfast performance. However, when designing complex and realistic applications, you may find that your application starts to become slow as the application size grows.

 

Meanwhile, if your application is not performing well, it will directly impact the end-user experience, which every programmer should avoid.

 

Further, it is essential to understand the underlying cause of poor performance in Angular applications with this thing in mind. First, you need to analyze your application and find the cause of the poor performance. Examine the code and determine if it followed the best practices. If not, you need to ensure that the application enforces the best rules and adheres to style guides and clean code architecture.

 

Here are some performance optimization techniques for improving the runtime of your Angular applications.

1. Lazy Loading of Modules

Lazy-loading is one of the most essential and most effective optimization tricks in the browser.


This is very effective; as a result it reduces the amount of bundled files loaded at the initial load of the webpage and only loads the resources that will be used directly in the webpage. All other resources doesn’t load.


They reload only when the user need them.


Angular provides a straightforward way to lazy-load resources.


To configure lazy loading in the Angular routers, we do this:

 

const routes: Routes = [
  {
    path: '',
    component: HomeComponent
  },
  {
    path: 'about',
    loadChildren: () => import("./about/about.module").then(m => m.AboutModule)
  },
  {
    path: 'service',
    loadChildren: () => import("./service/service.module").then(m => m.ServiceModule)
  }
]
​
@NgModule({
  exports: [RouterModule],
  imports: [RouterModule.forChild(routes)]
})
​
class AppRoutingModule {
} 

2. Preloading

Preloading is an optimization strategy that loads resources for future navigations or consumption. This speeds up both the loading and rendering of the resource because the help will already be present in the browser cache.

Angular has a preloading strategy implemented in its router module. This allows us to preload resources, routes, modules, etc., in our Angular application. The Angular router provides an abstract class PreloadingStrategy that all class implements to add their preloading strategy in Angular.

Below is the code to configure the preloading strategy property in the router configuration.

// ...   
​
RouterModule.forRoot([
  ...
], {
  preloadingStrategy: OurPreloadingStrategy
})
​
// ...   

 

3. “OnPush” Change Detection Strategy

Change detection is strongly related to Angular application performance. It is a convenient feature that helps a lot, but it can work against you if we do not misuse it.
The default behavior of change detection is that each change in your application leads to changing a single CD cycle and from top to bottom for all components.

The OnPush change detection strategy disables the change detection to run on a component and its children. Angular runs CD on the OnPush part when the app bootstraps and disables it. The Onpush element skips along with its children’s details in the subtree on subsequent CD runs.

If the inputs have referentially changed, change detection will only be run on the OnPush component.

@Component({
  selector: 'newsletter',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `...`
})
​
export class NewsletterComponent {
  ....
}

We can ask Angular to run CD by using detectChange method

 

@Component({
    ...
    template: `<div>{{data}}</div>`
})
​
class NewsletterComponent {
  data = 0;
  
  constructor(private changeDetectorRef: ChangeDetectorRef) {
    changeDetectorRef.detach()
  }
​
  clickHandler() {
    this.data++
    this.changeDetectorRef.detectChanges()
  }
​
} 

 

4. Use Pure Pipe

We use pipes to transform strings, currency amounts, dates, and other data for display. Pipes are simple functions to use in template expressions to accept an input value and return a transformed value. We can also pass additional arguments, like returning a difference of date from the start and end date.   

 

Angular also provides some built-in pipes for typical data transformations, including conversion of date into a string, and transformations for internationalization (i18n), which use locale information to format data.  

Pipes can be categorized into two types    

 

  1. Impure Pipe
    1. It produces different output for similar input over time  
  2. Pure Pipe
    1. It has a similar output for the same input  

 

Pure pipes introduce no side-effects, so the behavior is predictable, and we can cache the input to shortcut CPU-intensive operations to avoid recomputing them.   

 

Suppose we have used a function in a @Pipe that takes a reasonable amount of time before producing a result. 

@Pipe({
  name: "util"
})
​
class UtilPipe implements PipeTransform {
​
  func(val) {
    ...
​
    return ...;
  }
​
  transform(value) {
    return this.func(value)
  }
}

 

We will see that the func will hang the main thread that runs the UI and make the user wait to see the result. Now suppose the pipe is called every second; that will make a hell of an end-user experience.  

 

To lower the execution of this pipe, we must first note the pipe’s behavior; if it does not change data outside its scope (outside the pipe) then the pipe is a pure pipe. We cache the function results and return them when next time the function call with the same input.   

 

So for this, it is no matter how many times the pipe is called with an input, the func is called once, and the cached results are returned on subsequent calls.  

 

To add this behavior in @Pipe, we do this:

@Pipe({
  name: "util",
  pure: true
})
​
class UtilPipe implements PipeTransform {
 // ...
}  

 

With this, we tell Angular that this pipe is pure and doesn’t side-effect, so it should cache the outputs and return them when the inputs occur again.

5. Use trackBy option for *ngFor directive 

 

We are all familiar with the `*ngFor` directive, and it helps to repeat the same template for each collection item. Consider a scenario where you retrieve a list of accounts and display all account data on the page. Suppose a user adds a new account from the modal window; we reload the list of accounts again from the server and reassign the value to the list variable. This causes a re-rendering of `ngFor` directive.   

 

As mainly one user add the accounts, we only accept lists that get appended with a newly created account when a new list is re-fetched; this will make `ngFor` unnecessarily re-rendering the DOM. The reason is that ngFor removes all the DOM elements associated with the data and will re-create it even if the data is the same. Rendering an extensive collection on the page could be an expensive process.  

 

To solve this problem Angular provide us the trackBy feature to track elements when they are added or removed from the array list, `trackBy` accepts a function that returns the identity to compare with so, while rendering the template for each iteration, it stores value to default value against each template, so next time before rendering the template, it checks for the trackBy function value, if it is changed then only it re-renders the template. 

@Component({
    ...
    template: `
        <div *ngFor="let user of accounts; trackBy:trackByUserId">    
         ...  
        </div>    
​
    `
})
​
class AccountComponent {
  accounts = [];
​
  constructor() {
  }
  
  trackByUserId(index: number, accounts: any): string {
    return accounts.userId;
  }
​
} 

 

6. Optimize template expressions

Define your data/function in the component and render it on the DOM using double curly braces. For me, template expressions were one of the most useful features. Although we found it very useful, we still need to know the best practices for using Angular template expressions. 

We often run functions in templates: 

@Component({
  ...
  template: `<div>{{getDate()}}</div>`
​
})
​
class TestComponent {
  
  getDate() {
    ...
    
  }
​
}

 

When CD runs on the TestComponent this getDate will also run. Also, this getDate will have to complete before the CD, and other codes will move on.   

 

If the getDate function takes a long time to complete, users will experience drag or slowdowns. If a template expression becomes highly computational, don’t use it in the template or utilize caching on it.

7. NgZone or Outside the Angular

NgZone catches asynchronous operations from the Angular application. Meanwhile all code we write in Angular runs on the global zone; on the call stack Zone.js creates this zone to listen to async events (click, mouse move, etc.).   

Further after losing the power of change detection, even if Angular has the feature to disable the zone JS, the UI will not update. But we also have another option: the run outside-Angular zone.

 

Firstly, let’s take a look at the use case. It might occur in any place where you fire timers frequently, like setInterval, setTimeout. Let’s say we have to animate a car moving on track inside our angular app. Our animation code to move a car is in setInterval. 

@Component({
  ...
    template: `<div>   </div>`
})

class TestComponent {

  interval: any; 
  constructor(private ngZone: NgZone) {}
  
  processOutsideZone() {
    this.ngZone.runOutsideAngular(()=> {
      this.interval = window.setInterval(() => { 
        this.setPosition();
        this.repaint();
        }, 200)
    })
  }

}

 

Every 200ms, our car moves from its current position, and CD is also triggered each time. By default, CD is triggered whenever last function in call stack is executed — if it’s in the NgZone. 

 

So, every 200ms, on the call stack we put a callback from set Interval , and after execution of this function, the CD triggers on the root component. 

 

Further there is a simple way to fix it. You can wrap it with NgZone.runOutsideAngular. processOutsideZone runs the code outside the NgZone, and angular isn’t even “aware” that we fire these timers. 

A place for big ideas.

Reimagine organizational performance while delivering a delightful experience through optimized operations.

Conclusion

There go the top 7 best practices to boost your Angular application performance.   

To sum up, developing an Angular application is a straightforward task. Further, the challenging task is to optimize its performance for an excellent end-user experience. However, there are many ways of improving the performance of an application; incorporating some of the essential optimization techniques inside your web app development can help in optimizing and fine-tuning your Angular apps.  

Top Stories

Enhancing GraphQL with Roles and Permissions
Enhancing GraphQL with Roles and Permissions
GraphQL has gained popularity due to its flexibility and efficiency in fetching data from the server. However, with great power comes great responsibility, especially when it comes to managing access to sensitive data. In this article, we'll explore how to implement roles and permissions in GraphQL APIs to ensure that
Exploring GraphQL with FastAPI A Practical Guide to begin with
Exploring GraphQL with FastAPI: A Practical Guide to begin with
GraphQL serves as a language for asking questions to APIs and as a tool for getting answers from existing data. It's like a translator that helps your application talk to databases and other systems. When you use GraphQL, you're like a detective asking for specific clues – you only get
Train tensorflow object detection model with custom data
Train Tensorflow Object Detection Model With Custom Data
In this article, we'll show you how to make your own tool that can recognize things in pictures. It's called an object detection model, and we'll use TensorFlow to teach it. We'll explain each step clearly, from gathering pictures, preparing data to telling the model what to look for in
Software Development Team
How to deploy chat completion model over EC2?
The Chat Completion model revolutionizes conversational experiences by proficiently generating responses derived from given contexts and inquiries. This innovative system harnesses the power of the Mistral-7B-Instruct-v0.2 model, renowned for its sophisticated natural language processing capabilities. The model can be accessed via Hugging Face at – https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.2.Operating on a dedicated GPU server g4dn.2xlarge,
How to deploy multilingual embedding model over EC2
How to deploy multilingual embedding model over EC2?
The multilingual embedding model represents a state-of-the-art solution designed to produce embeddings tailored explicitly for chat responses. By aligning paragraph embeddings, it ensures that the resulting replies are not only contextually relevant but also coherent. This is achieved through leveraging the advanced capabilities of the BAAI/bge-m3 model, widely recognized for
Tracking and Analyzing E commerce Performance with Odoo Analytics
Tracking and Analyzing E-commerce Performance with Odoo Analytics
Odoo is famous for its customizable nature. Businesses from around the world choose Odoo because of its scalability and modality. Regardless of the business size, Odoo can cater to the unique and diverse needs of any company. Odoo has proven its capacity and robust quality in terms of helping businesses

          Success!!

          Keep an eye on your inbox for the PDF, it's on its way!

          If you don't see it in your inbox, don't forget to give your junk folder a quick peek. Just in case.









              You have successfully subscribed to the newsletter

              There was an error while trying to send your request. Please try again.

              Zehntech will use the information you provide on this form to be in touch with you and to provide updates and marketing.