Summary
Angular is great. React is great. Having written several Single Page Apps in each over the last few years, we’ve settled on React as our recommended environment for a variety of reasons. This article is intended for those facing a similar decision. Hope it helps!
Market Share (December 2018)
Since you are reading this, you probably already have a fair amount of background on how both of these major SPA tools emerged, so I won’t cover that here. Suffice to say that the first version of Angular was one of the most exciting tools out there around 2012 to 2014. Since then however, React has gained somewhat greater mind share in the developer community. Informally surveying some of the popular job boards (such as ziprecruiter, indeed, dice, etc.) for jobs open 30 days or less, it appears that react has about 20%-30% more job openings out there than the flavors of Angular, and that is even including the subset of Angular jobs that are “angular 1” or “angularjs” openings. Considering that Angular 1 is a dead end (with no practical relationship to Angular 2 and beyond, lets be honest), such openings are probably pretty maintenance intensive, and well on their way to being legacy systems (at which point their owners will begin looking at articles like this to figure out their next step). So we really shouldn’t include those jobs in the counts, but even if we do, React has a pretty big lead. Incidentally, Vue has about one-fifth the number of openings as Angular. Given the strength of the other two I don’t see room for it in the ecosystem but it may be worth keeping an eye on. I don’t use it and with such a small community (relatively), I wouldn’t recommend it for an enterprise.
Advantages and Disadvantages of Angular
Angular, of course, is a full-featured JavaScript framework. This is a paradigm that carries over well from the Java world, .Net, and even Cocoa and UIKit. Learn the framework’s approach and you can build your entire system that way, using those concepts and that style of coding across your entire team. Angular has its prescriptive way of breaking code into Modules, adding services via Dependency Injection, separating UI from logic via Components, handling css (Directives), implementing Routing, and even its own preferred flavor of Javascript (TypeScript). See the angular documentation for an overview. Angular can be considered as being very opinionated, and this has good and bad aspects. One thing Angular is not as opinionated about is whether or not to use Angular Material for your UI controls, which may surprise you. But it is very easy to integrate it with Angular, and that is no doubt intentional.
Let’s look at each of these topics in turn.
Angular Modules (NgModules) are an essential aspect of keeping code in “a cohesive block” (per the Angular documentation) for subsystems of the overall system, which may themselves encapsulate their own Components, Service Providers, etc. The Module concept is something you really would not want to be without, when building a system of non-trivial complexity. For what it does, it is a nice implementation that supports all of the usual concerns such as testing in isolation, encapsulation, loose coupling, etc. But in the end, it’s unfortunate that Angular requires the developer to learn yet another way of grouping up code into Modules. You have to learn it, you can’t get by without it and you wouldn’t want to. And its pretty easy to learn (though I guarantee you will make a mistake or two from time to time, and it will cost you an hour to find and fix). But it speaks to the heavyweight nature of a “framework” approach. As with pretty much all frameworks, we have to learn how Angular wants us to package up our subsystems. In the end this is more cruft than differentiator.
Angular uses Service Providers and Dependency Injection to connect frontend to backend. This is rather a 50,000 foot view but essentially that is what these concepts are used for. It is a well though-out, and standardized approach, again providing modularity and regularity which should in theory improve testing and speed up debugging. Angular’s own documentation says that Angular does not enforce this approach, but it helps you follow it (italics per the Angular docs). This is sophistry; these concepts are core to the framework. It’s true you don’t have to use them but then why are you using Angular in the first place? Their existence is not a minus though; there is something to be said for a totally standardized (“framework”) approach to getting data from somewhere else into your client.
Angular uses Components to represent, essentially, DOM elements, and Directives to represent their CSS styling. Again I am somewhat glossing over the nuances but you get the idea. The component lifecycle is managed by Angular. This aspect of Angular is probably where it is most similar to React at least in concept, if not precisely in operation. You can think of Angular Components similarly to the way you think of React Components and vice versa. If we make that analogy, then Angular here probably has an advantage over React in the sense that CSS modularization is a solved problem in Angular, whereas in React you need to choose your own way of managing that (it is only as of 2018 that a more robust approach is emerging in the React community, and it’s still got a ways to go in terms of technical maturity, let alone adoption).
Angular has its own built-in Router, whereas React does not, but by convention everyone uses React Router. We have to give the nod here to Angular, because clearly both environments face this problem universally and Angular chose to deal with it while React punted. So for instance when React Router 4 changed a lot from previous versions, that caused quite a bit of developer angst whereas Angular has that base covered automatically as part of its framework. Other than that it is unremarkable.
Regarding TypeScript, Angular does not mandate it, but typically it is preferred. TypeScript is a very nice object-oriented extension to JavaScript, in fact it’s my favorite flavor of JavaScript. It transpiles completely down into JavaScript (ECMA 3), so no worries on compatibility. But ES6 now has features like this, so TypeScript is fast losing its advantage. TypeScript was out waaaaay before ES6, and it was a weird (unholy?) alliance between Microsoft (the inventors) and Google (who via Angular are practically its sole non-Microsoft promoters), probably intended mostly to antagonize Apple. But it’s no longer a singular innovation, and it’s not as if the bonding between those two has further resulted in any major wins for developers. The bloom is off the rose.
Advantages and Disadvantages of React
Lets look at React in the context of our Angular discussion above.
As regards Modules, React does not have its own method. You simply uses the JavaScript modules as is. So whereas Angular has Modules as a first-class concept, React figures you have your own opinion about how your source code should be modularized. It’s hard to see how Angular’s approach is worth the effort. Still we can call this a push because modules, export/import/include etc. are very scattered around in JavaScript and Nodejs, so much so that sometimes its nice that there’s a standard approach to this concept in Angular.
Now with regard to Service Provision, Angular’s preferred approach is more than a little heavyweight, when fetch or something similar will get the job done. It looks prettier when you write your code in Angular. But its bigger, slower (a little), and doesn’t do anything special for you. React wins here, precisely because it has no prescriptive way to do this. You use any of the zillion packages available to do this very common thing depending on your preference (axios is hip as of this writing).
With respect to Components, let’s call it a push. Angular has two-way data binding and in React it is one-way, but I have yet to find a circumstance where this provided a practical advantage in Angular. It’s not worth the performance headaches that can come with it. React’s one-way binding and simple lifecycle hooks make it a little easier to debug (though easier to create a bug I think). In fact React would win this topic for me, except that Angular deserves credit for the fact that it has always had its preferred (if heavyweight again) mechanism for handling CSS scoping while React has no true consensus approach to this very important subject. Of course it’s not tremendously hard to do this the old fashioned way (manually controlling your namespaces), so long as you know what you are up against going in. On large distributed projects, Angular’s opinionated approach can save some headaches.
For Routing, the two approaches are similar. Angular has a de jure standard, React a de facto one. Not much difference here.
Finally regarding TypeScript, given the trends in ES6, it’s not as cool as it once was. One great thing about it is that it transpiles to JavaScript, so you have no worries about getting stuck in it if you try it, then want to go back. Still, long term I do not think it will catch on of its own right. Most likely it will merge in whole or in part into JavaScript (or the important parts will be mimicked in it).
React has its own TypeScript-ish thing, which is JSX. But JSX does look awfully like HTML, and is very, very easy to adopt for web programmers, who all already know HTML. There is virtually no learning curve. And the benefit of seeing your markup all in one spot with simple placeholders for injecting your app data helps in bug zapping. Angular separates things a little more with its Directives, which helps to prevent bugs, but then again, makes it harder to find them, and you end up with extra source files most likely.
Conclusion
Overall, we prefer React precisely because it is less opinionated, and less heavyweight (conceptually and literally) than Angular, while still supporting a pretty full feature set for developing and operating Single Page Apps, particularly when you consider its associated ecosystem. That is the overriding reason for selecting React, and that is enough. The Angular folks have gotten the runtime download size way down from what it once was, so that is really no longer a major reason to avoid Angular.
The main reason to go with React is because it is flexible, and blends much better with the rest of the JavaScript ecosystem. Why is that important, and why it is a reason to choose React, which makes you pick your own add-ons for critical functionality (like React Router 4 or axios), whereas with Angular you get that stuff out of the box?
Well, it all depends on your opinion, but our opinion is that as a first principle, we want to avoid situations where the maintenance of an app eventually becomes its most expensive phase. The React ecosystem is less monolithic, more flexible, and therefore we believe it is inherently more resilient in the long-run. If a new technology or a totally new approach emerges for handling a specific aspect of SPAs (think of the security space), React is more likely to be able to absorb those changes without a crushingly expensive rewrite. And as everybody knows, rewrites that expensive often get cancelled, spiraling into ever-increasing software debt. That, in the main, is why we recommend React over Angular.
In fact, for an example of why this type of resilience is so important, ironically we need look no further than the original Angular project itself. Google’s decision to make Angular 2 and future versions totally incompatible with Angular 1 (now called “angularjs”) almost killed Angular entirely, and surely provided an opening for React to become as widespread as it is. The flexibility of React seems to provide more insurance against a system becoming a stranded asset. The monolithic approach of the Angular framework is much more brittle. Maybe that’s why there are still so many “angularjs” job openings, when Google itself wants (or wanted) to retire it.