Why I no Longer Support Angular

In my “This Year in Review” post, I dropped a bombshell (at least to those who know me as Angular Evan):

These concepts, plus a team of nearly 100 developers in a single Angular project led me further and further away from suggesting Angular as a go-to framework.

I eluded to a few reasons as to why I don’t enjoy Angular as I used to and figure it warrants a full post. The main points I will focus on are the following:

  1. It is opinionated, which doesn’t scale
  2. Angular (v2+) syntax is awkward and unnatural
  3. There are better ways of managing state than injectables
  4. It hampers talented developers, instead helping them

Opinions, Opinions Everywhere!

Angular wooed me from day 1 when I first began working in the framework. There is an image I love about Angular from Ben Nadel that describes my first days in Angular.

This describes my experience very well. What it doesn’t show, however, is the aging of the framework. I learned how to be creative inside of the framework such as automatically appending headers to every HTTP request using `$httpProvider`, swapping out entire parts of the app with UI-Router and more. Things were great! Then my app turned 2 years old. I was fighting decisions I made a year before from an architecture point of view. My services became convoluted in order to meet individual use cases. It just became a spaghetti code mess.

I felt this was just the product of changing business requirements and little forethought (which had a role). However, when I got into my latest application, which has up to 100 developers working on it at a time, I found the “niceties” of Angular to actually begin to make the app terrible. Here are some of our pain points:

I don’t fault Angular for a lot of the above, but other frameworks are much more flexible around many of the points above. We avoided using services for business logic and instead use Redux (for the most part). Had we used services, this application would not be nearly as extensible as it has been.

As a result, the next framework I choose to work in will stick to rendering the view at best. React fits that very well, but I haven’t worked in a large scale application yet to be able to speak to it that well.

Awkward and Seemingly Unnecessary Changes

Angular 2+ piqued my interest when it first came out. I began researching it, got stuck on Typescript loaders, failed a few times, finally got it working, only to find out much of what I learned in 1.x did not transfer to Angular 2+ (you will note that I refuse to use AngularJS vs Angular, too). While I understand the benefits of Typescript, I don’t understand why Angular 2+ make it so difficult to be able to choose.

Other frameworks have the flexibility to use Javascript, Typescript, etc without being tied to a specific syntax. Angular 2+ nearly the use of decorators, at least if you want readable code.

<div *ngFor="let hero of heroes">{{hero.name}}</div> <input #heroInput> {{heroInput.value}}

In addition, it also chose to change the syntax of directives. Asterisks? Pound signs? What is this mess?!

My other complaint about these changes is that there is . If any of said boilerplate is done incorrectly, a useful error message is spat out to the developer to search on StackOverflow for. Much of this boilerplate helps solve the declaration issues that Angular 1.x had (duplication of component names, ensuring modules are properly instated, etc).

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

This is as simple as a module comes in Angular 2+. There is so much that a developer needs to know about the framework right off the get go, that the level of entry is already high out of the gate.

Managing State, Injectables vs Centralized Stores

As I eluded to in my Year in Review post, two particular concepts helped me realize how bad injectable services were. These concepts are immutability and stateless functions. Services don’t lend themselves well to either of these. Not only do you inject them into a variety of components, services and other constructs where changes made affect the rest of the application.

This could likely be solved by using immutable libraries to enforce changes to be made intelligently. However, at this point, the developer might as well implement a centralized store. Consider the scenario where there are multiple concepts (i.e. User data and Posts). In Angular, best practice eludes to using a service for each concept, and thus, two injectables are made. To combine these, a component either has to take in two injectables to get the proper data (not reusable beyond the component), or a third service created. With Redux (centralized store), any part of the store can be accessed and combined using the concept of selectors. These are stateless functions that produce a consistent result across the application.

The application I work on in my day job has probably 1000+ unique selectors. There are hundreds of reducers. Imagine each of reducer as a service, and each selector as a method on a service. The maintainability of that number of services would be astronomical. In addition, there is a possibility of state added to the service that could affect other areas of the app.

Hampering Talented Developers

The first year of my life in Angular was glorious. I had gone from a server generating HTML for the sake of my jQuery app to generating reusable components that dynamically changed DOM on the client side. Life was good.

My experience with Angular is that it is great for quick spin-ups. I can spin up an app and have a functioning site in less than a day. Write custom validators to support some odd business case? Sure thing, you’ve got it. Seems like magic, right?

I have come to find out, over 5 years of Angular development, that it just gets harder and harder to write high level code that just works. Dynamically loading modules was a pain. Debugging code as a result of a binding modifying a reference is difficult. Tracking down why my element flashes on the screen before hiding (thanks UI Grid for bringing in ng-animate without letting me know), horrid!

After nearly a year of being a team lead with extremely talented individuals, the biggest blocker to development has been Angular’s oddities. Watching a developer spend more time writing form error handling around the FormController kills me. Having had his focus on creating features instead of dealing with minute details would’ve made both the product owner and developer happier.

Don’t get me wrong, I initially fell in love with Angular as a result of a lot of the same features I complain about now. Form validation was super easy out of the box and I could prevent submission based on custom validators. As I developed opinions, ran into specific use cases, took a step back and looked at what I had to do on a daily basis, I’ve just come to find that Angular’s opinions trip up new developers as they struggle to understand, or hamper the development speed of the best developers.

Conclusion

I really look forward to the opportunity to try a new framework and do a “Turns out, this is a Every Framework Problem” post. Most libraries have oddities to overcome, but as the web continues to evolve, I believe that Angular will continue to fall by the wayside.

Front End Developer