DEV Community

Cover image for 10 Secret Angular Tricks for Better Performance and Cleaner Code
Chandan Kumar
Chandan Kumar

Posted on

10 Secret Angular Tricks for Better Performance and Cleaner Code

Angular is a powerful framework for building dynamic web applications, but some of its lesser-known features and techniques can significantly boost your productivity and application performance. Below, we explore 10 hidden techniques that every Angular developer should know to write cleaner, more efficient code.

1. Lazy Loading Modules for Performance
Lazy loading allows you to load Angular modules only when they are needed, reducing the initial bundle size and improving load times. Use the loadChildren property in your routing module to defer loading of feature modules.

Example:

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

2. TrackBy in *ngFor for Optimized Rendering
When using *ngFor to iterate over lists, Angular re-renders the entire list on changes. By adding a trackBy function, you can tell Angular to track items by a unique identifier, improving performance by only updating changed items.

Example:

`// In component
trackByFn(index: number, item: any): number {
return item.id; // Use unique identifier
}
// In template

{{ item.name }}`
3. Change Detection OnPush Strategy
The OnPush change detection strategy reduces unnecessary checks by only running change detection when input properties change or an event is triggered. This can significantly improve performance in large applications.

Example:

@Component({
selector: 'app-my-component',
template: '...',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyComponent {}

4. Using RxJS fromEvent for Custom Events
Instead of relying on Angular’s event bindings, you can use RxJS’s fromEvent to handle custom DOM events or third-party library events, providing more control and reactive programming benefits.

Example:

import { fromEvent } from 'rxjs';
ngOnInit() {
fromEvent(document, 'customEvent').subscribe(event => {
console.log('Custom event triggered:', event);
});
}

5. Dynamic Component Loading with ComponentFactoryResolver
Dynamically create components at runtime using ComponentFactoryResolver. This is useful for scenarios like modals or widgets that need to be injected dynamically.

Example:

constructor(private resolver: ComponentFactoryResolver, private container: ViewContainerRef) {}
loadComponent(component: Type) {
const factory = this.resolver.resolveComponentFactory(component);
this.container.createComponent(factory);
}

6. NgZone for Performance Optimization
Run specific tasks outside Angular’s zone to prevent unnecessary change detection cycles. This is particularly useful for third-party libraries or heavy computations.

Example:

constructor(private ngZone: NgZone) {}
runOutsideAngular() {
this.ngZone.runOutsideAngular(() => {
// Perform heavy task without triggering change detection
});
}

7. Custom Pipe Caching with Pure Pipes
Angular’s pure pipes are only re-evaluated when their inputs change. Create custom pure pipes to cache expensive computations, improving performance for repeated calculations.

Example:

@Pipe({
name: 'expensiveCalculation',
pure: true
})
export class ExpensiveCalculationPipe implements PipeTransform {
transform(value: number): number {
// Expensive computation
return value * 100;
}
}

8. Using providedIn: ‘root’ for Services
The providedIn: 'root' syntax for injectable services ensures singleton instances and enables tree-shaking, reducing bundle size by removing unused services.

`Example:

@Injectable({
providedIn: 'root'
})
export class MyService {}`
9. NgTemplateOutlet for Reusable Templates
Use NgTemplateOutlet to create reusable template fragments, reducing code duplication and improving maintainability.

Example:
`

{{ data.name }}


`
10. Resolver for Pre-fetching Data
Use Angular resolvers to fetch data before navigating to a route, ensuring the component has the necessary data when it renders, improving user experience.

Example:

@Injectable({ providedIn: 'root' })
export class DataResolver implements Resolve<any> {
constructor(private service: DataService) {}
resolve() {
return this.service.getData();
}
}
// In routing module
const routes: Routes = [
{
path: 'data',
component: DataComponent,
resolve: { data: DataResolver }
}
];

Conclusion
These hidden Angular techniques can help you write more efficient, maintainable, and performant applications. By leveraging lazy loading, optimized change detection, RxJS, and other advanced features, you can take your Angular development to the next level. Experiment with these techniques in your projects to see immediate improvements in performance and code quality.

📌 Stay Updated
Follow me for more design tips and tools! ✨

🐙 GitHub: Follow me for more web development resources.
🔗 LinkedIn: Connect with me for tips and tricks in coding.
✍️ Medium: Follow me for in-depth articles on web development.
📬 Substack: Dive into my newsletter for exclusive insights and updates:

Top comments (0)