Blog.

Some Angular Best Practices

Cover Image for Some Angular Best Practices
Michael
Michael

Best Practices for Angular Development

Angular is a powerful and popular front-end framework for building dynamic single page web applications. As projects grow in complexity, adhering to best practices becomes crucial for maintaining a clean and maintainable codebase. In this article, we'll explore some key best practices for Angular development based on the latest advancements in the framework.

1. Use Angular CLI

Angular CLI (Command Line Interface) simplifies the process of creating, building, testing, and deploying Angular applications. Start your projects with Angular CLI to benefit from its built-in generators, code scaffolding, and easy configuration.

ng new my-angular-app

Always generate new components and services using the built in CLI

ng generate <sub-command> <name>

or

ng g <sub-command> <name>

ng generate is your friend when it comes to boiler plate code generation, but remember to cd into the correct directory before running the command. Probably the most used throughout the project will be ng g class , ng g c (for components) and ng g s (for services)

2. Follow a Modular Project Structure

Organize your Angular project into modules, each serving a specific purpose. This modular approach improves code readability, encourages code reuse, and makes it easier to maintain and scale your application.

src/
|-- app/
|   |-- feature1/
|   |   |-- feature1.component.ts
|   |   |-- feature1.service.ts
|   |-- feature2/
|   |   |-- feature2.component.ts
|   |   |-- feature2.service.ts
|-- shared/
|   |-- components/
|   |   |-- shared-component1/
|   |   |-- shared-component2/
|-- core/
|   |-- services/
|   |   |-- api.service.ts
|   |   |-- auth.service.ts

By standardizing segregation of global services from components and shared modules, you can easily locate any required file as well as always knowing where to start working on any particular feature.

3. Use Lazy Loading for Modules

What is Lazy Loading? It is a technique in software development where certain parts of an application are loaded only when they are actually needed, thus saving resources and much prescious time when loading, giving user an overall better experience. After all, who likes waiting for a page to load?

Improve your application's initial load time by employing lazy loading for feature modules. This ensures that modules are only loaded when they are actually needed, enhancing the overall user experience. In a typical Angular application, all modules are loaded eagerly when the application starts. This means that the entire codebase, including all modules and their components, is loaded upfront, leading to a potentially longer initial loading time, especially in large applications.

So moving components and modules that are not used on initial load to be loaded lazily when they are going to be used, will improve load time without subtracting any features from the first page.

// app-routing.module.ts
const routes: Routes = [
  { path: 'feature1', loadChildren: () => import('./feature1/feature1.module').then(m => m.Feature1Module) },
  { path: 'feature2', loadChildren: () => import('./feature2/feature2.module').then(m => m.Feature2Module) },
];

In the above snippet, allows you to load specific modules only when the user navigates to a route that requires those modules. This helps in reducing the initial payload, improving performace by loading only essential parts need for the current user interaction.

Keeping this in mind, forces you to write more granular code, making you rethink wether or not a certain function would fit well in a given service.

4. Optimize Change Detection

Angular's change detection can be a performance bottleneck if not used carefully. Utilize the OnPush change detection strategy for components where possible. This strategy ensures that components only re-render when their input properties change.

Use OnPush Change Detection Strategy:

Angular provides different change detection strategies, and one of the most effective for optimization is the OnPush strategy. With OnPush, a component's change detection is triggered only when its input properties change or when an event is emitted from the component. This strategy reduces the number of checks and updates, improving performance.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}

Use Async Pipe for Observables:

When working with Observables, use the async pipe in the template. The async pipe automatically subscribes and unsubscribes, reducing the risk of memory leaks.

<p>{{ data$ | async }}</p>

Using TrackBy with ngFor

When using ngFor to iterate over a list, provide a track-by function to help Angular identify which items have changed. This can prevent unnecessary re-rendering of the entire list.

<div *ngFor="let item of items; trackBy: trackByFn">{{ item.name }}</div>

Then perform any operations in the given function

trackByFn(index, item) {
    console.log(`modified at ${index}`);
    return item.id; // Use a unique identifier for each item
}

5. RxJS Best Practices

Angular heavily relies on RxJS for handling asynchronous operations. Follow best practices for subscribing and unsubscribing to observables to avoid memory leaks. Use operators like takeUntil to automatically unsubscribe when a component is destroyed.

private destroy$ = new Subject<void>();

observable$
  .pipe(takeUntil(this.destroy$))
  .subscribe(data => console.log(data));

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

This setup will unsubscribe from observable$ when destroy$ is completed, and destroy$ is completed in the component onDestroy function, ensuring that nothing unexpected such as memory leaks occur once the component is destroyed.

Conclusion

By incorporating these best practices into your Angular development workflow, you'll be well-equipped to build scalable, maintainable, and performant web applications. Stay tuned for more insights into the latest Angular features and best practices as the framework continues to evolve.