DEV Community

Cover image for How to Improve an AngularJS Application Code
Meenakshi Agarwal
Meenakshi Agarwal

Posted on

How to Improve an AngularJS Application Code

AngularJS is getting more and more stable with every new release eliminating the waste and focusing on the advancement. Also, the big Software companies are now starting to rely on it to handle large scale projects.

In this post, we tried to highlight many such features which can in some way improve an AngularJS application or lead the way for a better implementation. These are suggestions which revolve around the Angular, TypeScript, ReactiveX, and some coding best practices.

TOC

1. Use trackBy with ngFor

In Angular, we mostly use the ngFor directive for iterating over a list of items. Here the problem is that you can't change the value of an object during the loop. It is simply because Angular doesn't track the items in the list and have no knowledge any addition or deletion.

However, if we add the trackBy option, then it can let Angular know which item has changed and will make changes specific to that only.

With the trackBy option, we can attach a function inside the ngFor clause which returns a unique identifier for each list item.

Angular Code using ngFor

<tr *ngFor="let set of sets;">
    <td><h1>{{set}}</h1></td>
</tr>
Enter fullscreen mode Exit fullscreen mode

Angular code using ngFor with the trackBy option

// Update the template
<tr *ngFor="let set of sets; trackBy: trackSet">
    <td><h1>{{set.name}}</h1></td>
</tr>

// Update the component
trackSet(index, set) {
    console.log(set);
    return set ? set.id : undefined;
}
Enter fullscreen mode Exit fullscreen mode

2. Fixed value or a variable, decide

You should maintain a clear distinction between what you use as a constant and those which will change their values.

Like many other languages, Angular also gives you built-in identifiers to disassociate a const from a variable.

Angular code without considering const vs. let guideline

let pen = 'parker pen';
let myPen = `My ${pen}`;
let yourPen = `Your ${pen};
if (iHaveParker) {
    myPen = `${myPen} is the best`;
}
if (youHaveParker) {
    yourPen = `${youPen} is the best`;
}
Enter fullscreen mode Exit fullscreen mode

Angular code using const vs. let guideline

const pen = 'parker pen';
let myPen = `My ${pen}`;
let yourPen = `Your ${pen};
if (iHaveParker) {
    myPen = `${myPen} is the best`;
}
if (youHaveParker) {
    yourPen = `${youPen} is the best`;
}
Enter fullscreen mode Exit fullscreen mode

3. Use of lightweight lettable operators

With ReactiveX (RxJS) 5.5, we saw the introduction of lettable (a.k.a. pipeable) operators.

More than operators, these are pure functions. They work as standalone operators replacing methods on an observable.

They’re pretty lightweight, turn your code highly re-usable and can reduce the overall build footprint.

Angular code without lettables

import { from } from 'rxjs/observable/from';

const numlist$ = from([1, 2, 3, 4, 5, 6, 7, 8, 9]);

numlist$
  .filter(x => x % 2)
  .map(x => x * 2)
  .scan((acc, next) => acc + next, 0)
  .startWith(0)
  .subscribe(console.log)
Enter fullscreen mode Exit fullscreen mode

Modified Angular code using lettables

import { filter, map, c } from 'rxjs/operators';

const doEven = filter(x => x % 2);
const doSum = reduce((acc, next) => acc + next, 0);
const doDouble = x => map(value => value * x);
Enter fullscreen mode Exit fullscreen mode

4. Use an operator when it matters the most

When you about to use an operator with the observables, select one after a careful assessment. Here are some quick examples of such situations.

a) If there comes a new emission and you wish to ignore the ones already occurred, then use the switchMap.

b) For concurrently handling all the emissions, use the mergeMap.

c) For handling the emissions one by one according to their entrance, use concatMap.

d) To suspend all new emissions while taking care of the current one, use exhaustMap.

It is a best practice to go with the single operator at a time instead of grouping multiple ones to gain the same effect.

5. Load a module when needed

It is called lazy loading, and it's not a new concept at all. However, apply it to the Angular code as well. For example, load an Angular component only when the application needs it.

With the lazy-loading enabled, the application will load a bit faster. Its boot time will improve by loading only the required set of modules.

Angular code w/o lazy loading

// File: app.routing.ts
{ path: 'not-lazy-loaded', component: NotLazyLoadedComponent }
Enter fullscreen mode Exit fullscreen mode

Angular code with lazy loading

// File: app.routing.ts
{ 
  path: 'target',
  loadChildren: 'target.module#TargetModule' 
}
// target.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { TargetComponent }   from './target.component';
@NgModule({
  imports: [
    CommonModule,
    RouterModule.forChild([
         { 
             path: '',
             component: TargetComponent 
         }
    ])
  ],
  declarations: [
    TargetComponent
  ]
})
export class TargetModule {}
Enter fullscreen mode Exit fullscreen mode

6. Declaration with type

Dynamic typing is a prominent feature, but it's best to specify the type while setting up variables in the code.

If we don't mention the type of variables, then it gets assigned at runtime based on the value. Sometimes, we could fall into problems due to this.

const a = 1;
const b = 'x';
const c = a + b;
console.log(`Value of c is: ${c}`)

// Result
Value of c is 1x
Enter fullscreen mode Exit fullscreen mode

In the above code, the problem is that we expect "b" as a number too. Such issues will not occur by giving them an appropriate type at the time of declaration.

const a: number = 1;
const b: number = 'x';
const c: number = a + b;

// This will give a compile error saying:
// Type 'x' is not assignable to type 'number'.
Enter fullscreen mode Exit fullscreen mode

7. Apply lint rules

We can improve the code by passing it through the lint rules. It will highlight coding issues instantly.

There is "tslint" which has built-in options such as "no-any," "no-magic-numbers", "no-console". We can set them inside the "tslint.json" to make them active for the code.

Angular code w/o lint

public ngOnInit (): void {
    console.log('Simple message');
    console.warn('Warning message');
    console.error('Error message');
}
Enter fullscreen mode Exit fullscreen mode

Upon execution, the code will run successfully and show the below in the console:

Simple message
Warning message
Error message
Enter fullscreen mode Exit fullscreen mode

Angular code with lint

// File: tslint.json
{
    "rules": {
        .......
        "no-console": [
             true,
             "log",    // console.log disabled
             "warn"    // console.warn disabled
        ]
   }
}
// File: xcomponent.ts
public ngOnInit (): void {
    console.log('Simple message');
    console.warn('Warning message');
    console.error('Error message');
}
Enter fullscreen mode Exit fullscreen mode

Upon execution, lint will show errors for "console.log()" and "console.warn()" statements. But there will not be any errors for the "console.error" as it was not in the configuration.

Calls to 'console.log' are not allowed.
Calls to 'console.warn' are not allowed.
Enter fullscreen mode Exit fullscreen mode

8. Split components to keep them small

If there are code-heavy components in your code, then pick and carve them into smaller pieces. See to make them as independent as possible so that they could work in most of the scenarios.

You can split a component if it doesn't have any particular logic and accepts inputs and processes them accordingly.

Such components are also known as Dumb because they are simple and have less prone to errors.

9. Make components specific for display purpose

Prevent components from adding any business logic other than the display related. It is best to limit them to show the data processed by the application.

Their purpose is to present the data and control how the view should operate. Don't mess them with any business logic instead have appropriate methods or services for them.

10. Remember DRY

You should not have the same code copied at several places in your application. Encourage regular code reviews in your team to spot any such malpractices sooner.

Maintaining duplicate code is an awful task and can quickly turn into a nightmare. Hence, you have to identify these problems as early as possible and stop a simple infection to become the ultimate decease.

Imagine if you are at the end of a release and have a problem to fix in such a code, then all affected area will need changes. It would only quadruply the dev and testing efforts.

Footnote

A developer's role is not only to produce robust and quality applications but also to make sure that they could sustain a desirable level of load as well.

And there is no magic wand which can instantly improve the quality. It is only possible by enacting the coding basics from the inception of the project and finding as well as doing changes to address challenges as and when they occur.

You can refer and learn more angular tips and best practices from this post on angularjs tips and trics.

Top comments (0)