Common Practices That Kill Performance in......

Common Practices That Kill Performance in Angular Applications.

Common Practices That Kill Performance in Angular Applications.

1. Excessive Change Detection

Bad Code:

Change detection is triggered too frequently, affecting performance.


@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
})
export class MyComponent {
  @Input() data: any;
}

Correction:

Use the OnPush strategy in components where possible. This makes change detection occur only when the component's input changes.


@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyComponent {
  @Input() data: any;
}


2. Inefficient DOM Manipulation

Bad Code:

Direct DOM manipulations can be inefficient and hard to manage.


ngAfterViewInit() {
  document.getElementById('elementId').style.color = 'blue';
}


Correction:

Use Angular’s Renderer2 to manipulate the DOM more efficiently.


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

constructor(private renderer: Renderer2) {}

ngAfterViewInit() {
  const element = this.renderer.selectRootElement('#elementId');
  this.renderer.setStyle(element, 'color', 'blue');
}


3. Overuse of Pipes

Bad Code:

Pipes that perform heavy operations can be re-executed frequently, hurting performance.


@Pipe({
  name: 'heavyPipe',
  pure: false
})
export class HeavyPipe implements PipeTransform {
  transform(value: any): any {
    // Heavy transformation logic
  }
}

Correction:

Use pure pipes (pure: true) for lightweight operations or avoid pipes for heavy operations.


@Pipe({
  name: 'heavyPipe',
  pure: true
})
export class HeavyPipe implements PipeTransform {
  transform(value: any): any {
    // Light transformation logic
  }
}


4. Excessive Initial Load

Bad Code:

Loading all modules and components at initialization can delay loading time.


@NgModule({
  declarations: [AppComponent, FeatureComponent],
  imports: [BrowserModule, FeatureModule],
  bootstrap: [AppComponent]
})
export class AppModule {}


Correction:

Use lazy loading for modules that are not immediately needed.


const routes: Routes = [
  { path: 'feature', loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule) }
];


5. Unmanaged Subscriptions

Bad Code:

Not cancelling subscriptions can lead to memory leaks.


ngOnInit() {
  this.myService.myObservable.subscribe(value => {
    // Do something with value
  });
}


Correction:

Use the async pipe or manage subscriptions with takeUntil or Subscription.


import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  constructor(private myService: MyService) {
    this.myService.getData()
      .pipe(takeUntil(this.destroy$))
      .subscribe(data => {
        // Handle the data
      });
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}


For Angular 16+ use takeUntilDestroyed.

import { Component, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponent implements OnInit, OnDestroy {

  constructor(private myService: MyService) {
  }

  ngOnInit(): void {
    this.myService.getData()
      .pipe(takeUntilDestroyed(this))
      .subscribe(data => {
        // Handle the data
      });
  }

  ngOnDestroy() {
  }
}



Share Article:
  • Facebook
  • Instagram
  • LinkedIn
  • Twitter
  • Recent Posts