At Agira, Technology Simplified, Innovation Delivered, and Empowering Business is what we are passionate about. We always strive to build solutions that boost your productivity.

Angular Best Practices – Top 10 Things You Should Know

  • By Nagaraj Ravi
  • May 27, 2019
  • 1588 Views

Being a full-stack developer, I always had a special love on Angular that would always push me to explore something new in it every day. I had like to put all those effective & interesting tips together which helped me a lot in my development and also received loads of positive responses from our team & from our clients for achieving 10X more quality in a short time. Keeping all these in mind, today I planned to share Angular best practices that I know with every Angular developer who is striving to learn & project them as a complete Angular developer.

So, If you’re facing any conflicts in Angular development and it’s performance then this guide will help you to achieve high performance, scalability, security on full swing adhering to the standards maintained by Angular.

Let’s explore the most effective Angular best practices,

  • Angular folder structure best practice
  • The lazy loading feature module
  • Track by
  • CDK Virtual scroll
  • Angular coding styles
  • Avoid observables memory leaks
  • index.ts
  • Some most useful ES6 new Features
  • State management
  • switchMap vs mergeMap vs concatMap vs exhaustMap

1. Angular Best Practices -Folder Structure

While working on a medium-sized or large project, creating the folder structure is a very significant factor as it can bring loads of problems in the future in case if it’s structured in the wrong way. 

Whenever we are working on a project, we may have to go through lots of changes. Thereby our project should easily adapt to the new changes. Creating a good folder structure will help us to manage and adapt things easily.

Let’s see the following folder structure for example and you can get the source code for it here.

|-- src
       |-- app
          |-- angular-material
          |-- auth
              |-- components
              |-- containers
              |-- auth.component.ts | html | scss | spec.ts
              |-- auth.module.ts
              |-- auth.routing.module.ts
          |-- common
          |-- config
              |-- app.config.ts
              |-- config.module.ts
              |-- index.ts
          |-- core
              |-- layouts
                  |-- compnents
              |-- models
                  |-- interfaces
                     |-- http
                         |-- payloads
                         |-- response
                         |-- index.ts
                  |-- enums
                      |-- contstants.enum.ts
                      |-- index.ts
              |-- providers
                  |-- guards
                  |-- http
                  |-- http-interceptors
                  |-- index.ts
          |-- home
              |-- components
                  |-- header
                      |-- header.component.ts | html | scss | spec.ts
              |-- pages
                  |-- candidates
                      |-- components
                          |-- data-table.component.ts | html | scss | spec.ts   
                          |-- profile.component.ts | html | scss | spec.ts
                          |-- index.ts
                      |-- containers
                          |-- list
                              |-- list.component.ts | html | scss | spec.ts  
                      |-- store
                          |-- store.module.ts
                      |-- candidates.component.ts | html | scss | spec.ts
                      |-- candidates.module.ts
                      |-- candidates-routing.module.ts
                 |-- home.component.ts | html | scss | spec.ts
                 |-- home.module.ts
                 |-- home-routing.module.ts                   
          |-- app.component.ts | html | scss | spec.ts
          |-- 404.ts  
          |-- app-routing.module.ts
          |-- shared
              |-- components
              |-- directives
              |-- pipes
              |-- shared.module.ts
          |-- store
              |-- auth
              |-- state.ts
              |-- store.module.ts      
       |-- assets
          |-- css
          |-- images
          |-- icons
          |-- js          
       |-- environments
       |-- scss
           |-- classes
           |-- mixins
           |-- functions
           |-- _index.scss
           |-- _theme.scss
           |-- _reboot.scss
           |-- _variable.scss
           |-- _layout-common.scss    
       |-- styles.scss

Angular Core module Vs Shared Module

Core Module

  • Create a CoreModule with providers for the singleton services you load when the application starts.
  • Never import CoreModule in any other modules because you should import this CoreModule only in the AppModule.
  • You can create a layout component also like header, footer, side menu.
  • If any of the components you’re going to use only once in an application throughout the process then make sure to keep all these components in Layouts folder inside of the core folder which can help us to maintain the standard.
  • Can create a feature module named as “CoreModule” in a core folder like below
for example, app/core/core.module.ts defines CoreModule

Shared Module

  • Create a feature module named SharedModule in a shared folder; for example, app/shared/shared.module.ts 
  • Create a SharedModule with the components, directives, and pipes that you use everywhere in your app. This module should consist of entire declarations, most of them will be exported. Also, make sure to avoid using any services at the root level.

Config Module

  • Create a feature module named Config Module in a config folder. For example, app/config/config.module.ts
  •  Create configuration services or configuration APIs in the config folder.

Home Module

  • Create a feature module named HomeModule in a home folder; for example, app/home/home.module.ts
  • Create a page in this home folder and set up routing for the page in the home-routing.module.ts. If the project seems somehow medium or big sized then you can create every page as a feature module as lazy loading else you can declare the page component in home.module.ts itself if the project seems small.

Store Module

Create a store module for state management. You can create a store module in the app/store for managing the globalized states which will be available all over the application. Finally, create the feature store module in a particular page component’s own folder itself to maintain its states. For example, app/home/pages/profile/store

Structuring SASS Project 

This folder contains all of your styles file. Create subfolder like classes, functions, mixin( for SCSS).  You can structure it as per your chosen style standard. While writing styles, try to use SASS features instead of using plain CSS this will avoid code redundancy which results in reducing the code size.

2. Lazy Loading Feature Module

Lazy loading is a design pattern in the programming language which is prebuilt in angular that used to load the things when it’s required. In Angular Lazy loading, only the feature module will load the component, pipes, decorators when it’s required also it will stop loading unnecessary components when it’s not required. This is the most important thing while working with the medium or large level angular project as it decreases the Page loading time.
You can more learn about this here (here).

3. TrackBy In Angular

TrackBy will uniquely identify each item in the collection by tracking the association between DOM and each item.
You can make use of the track by index when you do not have any unique identifier else you can set the identifier for the”track by” this will track the Particular id of the item. If you are using “track by” then it will avoid generating DOM elements every time for the element that are already rendered. It improves rendering performance and avoids changing the order of the items.

Example

component.html

<ul>
            <li *ngFor="let post of posts;trackBy:identify"> {{post.data}} </li>
  </ul>
  Component.ts:
  Class component{
    identify(index,item){  return post.id }
  }

4. CDK Virtual Scroll

CDK Virtual scroll comes from Angular material package. “<cdk-virtual-scroll-viewport>” It’s used to show the largest list in the browser and also used to increase the performance of the Browser application. When you are trying to load more than hundreds of items at the same time, it will slow down the browser performance.  In that case, virtual scrolling will be used to increase the performance and view all the items being rendered. Before that, you have to set the height for the “<cdk-virtual-scroll-viewport>” then only it will render on the view.

Example

component.html

<cdk-virtual-scroll-viewport itemSize="50" class="example-viewport">
   <div *cdkVirtualFor="let item of items"      class="example-item">{{item}}</div>
  </cdk-virtual-scroll-viewport>

Component.ts

export class CdkVirtualScrollOverviewExample {
   items = Array.from({length: 100000}).map((_, i) => `Item #${i}`);
  }

Component.css

.example-viewport {
   height: 200px;
   width: 200px;
   border: 1px solid black;
  }
  .example-item {
    height: 50px;
  }

5. Angular Coding Styles

Coding styles are very important things we should focus on in any programming language. The project should contain a clean code that should be simple, understandable and easily adaptable by another programmer.

Follow the angular official style guide for structure and angular things. And you can follow the Bem methodology for styling the styles(CSS, SCSS) and google HTML style guide for HTML.

I have stated the some important rules for the angular style guide which is good to follow by:

  • Write code up to 400 lines per file.
  • Write code up to 75 lines per function.
  • Try to use the custom prefix for a component selector. For example, the prefix shared represents a shared feature area for a range slider component.

Example

Shared-range-slider

  • Declare variables with “const”‘ if their values have not changed.
  • Avoid prefixing for interface names like IShape, AbstractShape.
  • Declare the properties and methods name in lower camel case to name.
  • Separate the third party imports and application imports by one empty line between a third-party module and custom module.
Looking for a Tech partner to dominate the digital world?
Let’s Discuss

6. Avoid Observable Memory Leaks

Async Pipe

You can use the subscribed observables or promise in the view itself by using the async pipe. It represented by “async” name. Avoid the subscribing in component and binding that in view. If you have not set the “Complete observable” technique then it will lead to memory leaks and the async pipe will destroy the observable when the component is destroyed.

Example

<ul>
      <li *ngFor="let item of items | async">{{item?.name}}</li>
  </ul>

take(1)

take(1) operator takes the first value and completes the emission. Thereby it will not subscribe when the new value observed. So we don’t have to worry about the memory leaks. Use this when you need to get the data only once.

Example

data$.pipe(take(1)).subscribe(res=>console.log(res))

takeUntil

Use takeUntil operator when you want to complete the observables when you want to listen to the observables till the component is going to be destroyed. See the following example. You can do as follow.
Create an observable Subject instance.
Use takeUntil operator pass the Subject instance in the pipe.
Add the ngUnsubscribe.next() and this.ngUnsubscribe.complete() in ngOnDestroy().
It will stop the emission when your component is destroyed.

export class component{
  private ngUnsubscribe: Subject<void> = new Subject<void>();
  constructor(){
  }
  ngOnInit() {
  this.state$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(data   => {
  console.log(data);
  });
  }
  ngOnDestroy(): void {
     this.ngUnsubscribe.next();
     this.ngUnsubscribe.complete();
   }
  }

You can also more about it here,

Also Read: How To Prevent Memory Leaks In Angular Observables

7. Index.ts

Index.ts file is another important thing in an Angular project that helps to reduce the import statement sizes. See the following example, we can export the modules in index.ts and import all the modules in app.module.ts instead of importing all the modules in one place.

Example

heroes/index.ts:
  export * from './hero.model.ts';
  export * from './hero.service.ts';
  export { HeroComponent } from './hero.component.ts';
  app.module.ts”
  import { Hero, HeroService, HeroComponent } from '../heroes';

8. Some Most Useful ES6 Features

 There are some new ECMAScript standard features that will help the code look simple and better. Let us see the following.

let and const

Declare the variable with let and const instead of var. It will avoid “var” based problems. In case if the value doesn’t change then you can it declare with const else declare with let.

For example

let temp;
  Const pi = 3.14159

Spread Operator

 It is represented by three consecutive dots which is the most important feature in ES6. It is mostly used to cocat the collection in an array and also used to shallow clone the object and object property concatenation in an object.

Example For Array

         const list = [1,2,3];
           const tempList = [...list];

Example In Object

         const obj= {id: 1}];
           const copyObj = {..obj}

Array Predefined Methods

Use some predefined methods like find, from, includes, of, reduce as these will avoid using the Of some unnecessary array utility libraries like lodash and underscore.js, etc.

Block-scope variables within switch statements

Usually, we will get a syntax error when you are declaring the same variable name in two different switch case. In that case, you can avoid this using a block scop switch case.

Example

        switch(shape){
              case ‘square’:{
                 let area = ‘10m’
                 break;
               }
               case ‘rectangle ’:{
                 let area = ‘15m’;
                  break;
               }
  default:{
  break;
  }
  }

9. State Management

State management is important for a medium and large level project to maintain the states. There are some frameworks available for angular like NGRX, NGXS, REDUX. You can use any of this to maintain a state but NGXS is suggested by most of them due to it’s easy to learn, removing boilerplates and it’s first-party plugins. There is a redux state management development tool is available for you in which you can analyze the Action and states in that tool itself.

10. Useful RxJS Transformation Operators

ConcatMap

When we are using concatMap with actions that should be neither aborted nor ignored and the order of the action will never be changed.

MergeMap

When we are using mergeMap with actions that should be neither aborted nor ignored but you can not expect the orders.

SwitchMap

If you are using switchMap actions, it should be aborted when another action of the same type is dispatched;

ExhaustMap

When we are using exhaustMap with actions that should be ignored when an action of the same type is pending.

switchMap vs mergeMap vs concatMap vs exhaustMap

  •     Use switchMap only for reading.
  •     Use concatMap for creating, update, delete operation when you need the data in order as per the Action dispatched.
  •     Use mergeMap for creating, update, delete operation when you are not expecting orders.
  •     Use for exhaustMap for ignoring new Observables If the current one is still ongoing.

Other Useful Top Angular Best practices

  • Use NGXS for state management and while using these frameworks like NGXS, NGRX, REDUX, we should clearly know when & where to use it.
  • Following Pro HTML and CSS design patterns for creating styles are some of the awesome tricks that really help you to increase your designing knowledge.
  • Use OOAD (Design pattern), this will make your project reusable, clean and neat. Also try to utilize some common patterns like Singleton, Facade, Observe, factory, strategy patterns to use it.
  • Avoid using multiple web design frameworks as this can help us to avoid any theme collision.
  • Use SVG type icons instead of using images & use angular flex layout to reduce the amount of styles code.
  • It’s better to avoid using Loadsh or other libraries even for simple array utilities since there are some of the cool predefined methods available in javascript itself.
  • We should know the use of navigator.onLine which is used to check whether the network is connected or not.
  • Use web pack proxy if you are going to use the build file in the same backend server instead of using it in the separate server of the frontend as it will avoid adding CORS set up in the backend dev server.
  • Use MICRO FRONTEND architecture for a large-sized project to avoid maintainability and deployment problems.
  • Avoid manipulating the DOM elements directly instead you can use the Angular framework.
  • Importing or injecting the services line by line will help us to manage the code in git to avoid any conflicts. See the following example.

Also Read: Top 10 Angular Blogs You Must Not Miss

References

The following references will help you to understand and implement for Angular best practices.

  • SOLID principles
  • Design Patterns
  • Clean Code [book]
  • Bem Methodology
  • Por HTML5 and CSS3 Design pattern [book]

Are you looking for Angular developers to build your application? Here is the comprehensive guide on how to hire Angular developers. Also, it guides you with the following topics.

  • Angular developer skills.
  • How an ideal Angular developer resume should look.
  • Top Angular developer tools.
  • Commonly asked Angular developer interview questions.
  • Present Angular developer job opportunities.

Turn your vision to magnificent reality With Our Web and Mobile Solutions Request Quote

Nagaraj Ravi

A zealous full stack web developer with 3 years of professional experience. Hybrid application development and in developing Open-source projects are the best of my list. Out of passion ethical hacking is one of my hobbies. Yet, I am good at analyzing Web Security. And I teach machines with my expertise in Robotics and Machine learning.