Change detection is triggered too frequently, affecting performance.
@Component({ selector: 'app-my-component', templateUrl: './my-component.component.html', }) export class MyComponent { @Input() data: any; }
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; }
Direct DOM manipulations can be inefficient and hard to manage.
ngAfterViewInit() { document.getElementById('elementId').style.color = 'blue'; }
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'); }
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 } }
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 } }
Loading all modules and components at initialization can delay loading time.
@NgModule({ declarations: [AppComponent, FeatureComponent], imports: [BrowserModule, FeatureModule], bootstrap: [AppComponent] }) export class AppModule {}
Use lazy loading for modules that are not immediately needed.
const routes: Routes = [ { path: 'feature', loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule) } ];
Not cancelling subscriptions can lead to memory leaks.
ngOnInit() { this.myService.myObservable.subscribe(value => { // Do something with value }); }
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() { } }