Angular or React?
Each framework has much to offer and the decision between them isn't simple. Whether you’re a newcomer, a freelancer deciding on a framework for your next project, or an enterprise-grade architect planning a strategic vision for your company, a comparison is definitely helpful. This article won’t give a clear answer on which framework is better, but it will assist in comparing the two frameworks so your team can make the educated guess for your next use case.
Where to Begin?
Before you make a decision on a framework, you need to determine the answer to two questions:
- Is this a good tool?
- Will it work well for my use case?
Since all the questions might not be that simple, let's break them down into smaller ones.
Questions on the tool itself:
- How mature is it and who’s behind it?
- What kind of features does it have?
- What architecture, development paradigms, and patterns does it employ?
- What is the ecosystem around it?
Questions for self-reflection:
- Will I and my colleagues be able to learn this tool with ease?
- Does it fit well with my project?
- What is the developer experience like?
Using this set of questions you can start your assessment of any tool and base the comparison of React and Angular on them as well.
There’s another thing to take into account. It’s not completely fair to compare Angular to React, since Angular is a full-blown, feature-rich framework, while React is a UI component library. For a more even comparison, React will be spoken about in conjunction with some of the libraries often used with it.
An important part of being a skilled developer is being able to keep the balance between established, time-proven approaches and evaluating new bleeding-edge tech. As a general rule, you should be careful when adopting tools that haven’t yet matured due to certain risks:
- The tool could be buggy and unstable
- It might be unexpectedly abandoned by the vendor
- There might not be a large knowledge base or community available in case you need help
Thankfully, both React and Angular come from good families, so it seems that we can be confident in this regard.
React is developed and maintained by Facebook and used in their own products, including Instagram and WhatsApp. It has been around for around five years now, so it’s not exactly new. It’s also one of the most popular projects on GitHub, with about 119,000 stars at the time of writing.
Angular has been around less then React, but it’s not a new kid on the block. It’s maintained by Google and is used in more than 600 hundred applications in Google such as Firebase Console, Google Analytics, Google Express, Google Cloud Platform and more.
As mentioned earlier, Angular has more features out of the box than React. This can be both a good and a bad thing, depending on how you look at it. Both frameworks share some key features in common: components, data binding, and platform-agnostic rendering.
Angular provides a lot of the features required for a modern web application out of the box. Some of the standard features are:
- Dependency injection
- Templates, based on an extended version of HTML
- Routing, provided by @angular/router
- Ajax requests using @angular/common/http
- @angular/forms for building forms
- Component CSS encapsulation
- XSS protection
- Utilities for unit-testing components.
Some of these features are built-in into the core of the framework and there's no option not to use them. This requires developers to be familiar with features, including dependency injection to build even a small Angular application. Other features such as the HTTP client or forms are completely optional and can be added on an as-needed basis.
With React, you’re starting off with a more minimalistic approach. If we’re looking at just React, here’s what is available:
- No dependency injection
- State management using setState and the Context API.
- XSS protection
- Utilities for unit-testing components.
Not much, but this can be a good thing! It means that you have the freedom to choose whatever additional libraries to add based on your needs. The unfortunate thing is that you have to make those choices yourself. Some of the popular libraries that are often used together with React are:
- React-router for routing
- Fetch (or axios) for HTTP requests
- A wide variety of techniques for CSS encapsulation
- Enzyme for additional unit-testing utilities.
The freedom of choosing your own libraries can be liberating! It gives the ability to tailor your stack to particular requirements of each project, and the cost of learning new libraries isn't too high.
Languages, Paradigms, and Patterns
Taking a step back from the features of each framework, consider what higher-level concepts are popular with both frameworks.
There are several important things that come to mind when thinking about React: JSX, functional components, state management, PropTypes, and Flow.
In React, you can define components using functions and classes. Functional components are usually pure and provide a clear mapping between in the input props and the rendered output. Functional code is usually less coupled and easier to reuse and test. However, functional components in React have their limitations. For example, they cannot have a state as opposed to the class components. This requires the developers to switch between the two paradigms to make the best of both worlds.
The situation will change when the hooks proposal is finalized. This will allow functional components to have a state and use other features of class components, such as lifecycle hooks.
The concept of state management is important for both frameworks and React has several approaches to offer. Each component can have its own state, so you can use that to create stateful components for holding the state of a part of the application. This is known as the lifting state up pattern. This, however, gets impractical as you need to store global state required in different parts of the application as well as manually pass data around different levels of the component tree. To mitigate this, React 16.3 introduced the Context API that allows you to make data available an all component tree levels without passing it around explicitly. Contexts don’t store the state themselves, they only expose the data, but if you wrap it in a stateful component you can implement a convenient natively supported way to store the state.
There are also third-party libraries for state management in React. Redux is a state management library inspired by Flux, but with some simplifications. The key idea of Redux is that the whole state of the application is represented by a single object, which is mutated by functions called reducers. Reducers themselves are pure functions and are implemented separately from the components. This enables better separation of concerns and testability.
MobX is an alternative library for managing the state of an application. Instead of keeping the state in a single immutable store, as Redux does, it encourages you to store only the minimal required state and derive the rest from it. It provides a set of decorators to define observables and observers and introduce reactive logic to your state.
PropTypes is an optional feature of React that can bring additional safety measures if you’re not using Flow or TypeScript. It allows you to define a set of validators for the props of components that will check their values at runtime. Since React 15.5 prop types have been moved to a separate prop-types library and are now completely optional. Considering its benefits, it is advised to use it to improve the reliability of your application.
Unlike TypeScript, which has a similar purpose, it does not require you to migrate to a new language and annotate your code for type checking to work. In Flow, type annotations are optional and can be used to provide additional hints to the analyzer. This makes Flow a good option if you would like to use static code analysis, but would like to avoid having to rewrite your existing code.
All three features can greatly improve your developer experience: JSX, Flow, and PropTypes allow you to quickly spot places with potential errors, and carefully choose your aproach to state management will help achieve a clearer structure for your project.
Angular has a few interesting things up its sleeve as well, namely TypeScript, RxJS, and Angular Elements, as well as its own approach to state management.
RxJS is a reactive programming library that allows for more flexible handling of asynchronous operations and events. It’s a combination of the Observer and Iterator patterns blended together with functional programming. RxJS allows you to treat anything as a continuous stream of values and perform various operations on it such as mapping, filtering, splitting or merging.
The library has been adopted by Angular in their HTTP module as well for some internal use. When you perform an HTTP request, it returns an Observable instead of the usual Promise. This approach opens the door for interesting possibilities, such as the ability to cancel a request, retry it multiple times or work with continuous data steams, such as web sockets. But this is just the surface. To master RxJS, you’ll need to know your way around different types of Observables, Subjects, as well as around a hundred methods and operators.
Similar to React, Angular components can store data in their properties and pass them to their children. If you need to access values in sibling components you can move it to a stateful service that can later be injected into the components. Since reactive programming and RxJS is a first-class citizen in Angular, you can make use of observables to recalculate parts of the state based on some input. This, however, can get tricky in larger applications since changing some variable can trigger a multi-directional cascade of updates that is difficult to follow.
NgRx, the most popular state management library for Angular can make things easier. It’s inspired by Redux but also makes use of RxJS to watch and recalculate data in the state. Using NgRx can help you enforce an understandable unidirectional data flow as well as reduce coupling in your code.
NGXS is another state management library inspired by Redux. In contrast to NgRx, NGXS strives to reduce boilerplate code by using modern TypeScript features and improve the learning curve and overall development experience.
TypeScript has been found to be a great tool for improving the maintainability of our projects, especially those with a large code base or complex domain/business logic. Code written in TypeScript is more descriptive and easier to follow. RxJS introduces new ways of managing data flow in your project but does require you to have a good grasp of the subject. Otherwise, it can bring unwanted complexity to your project. Angular elements have the potential for re-using Angular components and it’s interesting to see how this plays out in the future.
The great thing about open source frameworks is the number of tools created around them. Sometimes, these tools are even more helpful than the framework itself. Take a look at some of the most popular tools and libraries associated with each framework.
A popular trend with modern frameworks is having a CLI tool that helps you bootstrap your project without having to configure the build yourself. Angular has Angular CLI. It allows you to generate and run a project with just a couple of commands. All of the scripts responsible for building the application, starting a development server and running tests are hidden away from you in node_modules. It can also be used to generate new code during development and install dependencies.
Angular introduces an interesting new way of managing dependencies to your project. When using ng add you can install a dependency and it will automatically be configured for usage. For example, when you run ng add @angular/material, Angular CLI downloads Angular Material from the npm registry and runs its install script that automatically configures your application to use Angular Material. This is done using using Angular schematics. Schematics are a workflow tool that allows the libraries make changes to your code base. This means that the library authors can provide automatic ways of resolving backward-incompattible issues you might face when installing a new version.
Ionic is a popular framework for developing hybrid mobile applications. It provides a Cordova container that is nicely integrated with Angular and a pretty material component library. Using it, you can easily set up and build a mobile application. If you prefer a hybrid app over a native one, this is a good choice.
There’s a Material component library available for Angular with a good selection of ready-made components.
Angular universal is a project that bundles different tools to enable server-side rendering for Angular applications. It is integrated with Angular CLI and supports a number of Node.js frameworks, such as express and hapi, as well as with .NET core.
Augury is a browser extension for Chrome and Firefox that helps to debug Angular applications running in development mode. You can use it to explore your component tree, monitor change detection and optimize performance issues.
Create React App
Create React App is a CLI utility for React to quickly set up new projects. Similar to Angular CLI it allows you to generate a new project, run the app in development mode or create a production bundle. It uses Jest for unit testing, supports application profiling using environment variables, backend proxies for local development, Flow and TypeScript, Sass, PostCSS, and a number other features.
React Native is a platform developed by Facebook for creating native mobile applications using React. Unlike Ionic, which produces a hybrid application, React Native produces a truly native UI. It provides a set of standard React components which are bound to their native counterparts. It also allows you to create your own components and bind them to native code written in Objective-C, Java or Swift.
There’s a material design component library available for React as well. Compared to Angular’s version, this one is more mature and has a wider range of components available.
Next.js is a framework for the server-side rendering of React applications. It's a flexible way to completely or partially render your application on the server, return the result to the client, and continue in the browser. It assists in making the complex task of creating universal applications easier so the set up is designed to be as simple as possible with a minimal amount of new primitives and requirements for the structure of your project.
Gatsby is a static website generator that uses React.js. It allows using GraphQL to query the data for your websites defined in markdown, YAML, JSON, external API’s as well as popular content management systems.
React 360 is a library for creating virtual reality applications for the browsers. It provides a declarative React API that is built on top the WebGL and WebVR browser APIs thus making it easier to create 360 VR experiences.
React Developer Tools
React Dev Tools is a browser extension for debugging React applications that allows you to move through the React component tree and see their props and state.
Adoption, Learning Curve and Development Experience
An important criterion for choosing a new technology is ease of learning. The answer depends on factors such as previous experiences and general familiarity with the related concepts and patterns. However, the number of new things needed to learn to get started with a given framework can be assessed.
The official tutorial is an excellent place to start learning React. Once you’re done with that, get familiar with the router. The React Router v4 might be slightly complex and unconventional, but nothing to worry about. Depending on the size, complexity, and requirements of your project you’ll need to find and learn some additional libraries and this might be the tricky part, but after that everything should be smooth sailing.
It's genuinely easy to get started using React. Even people with a back-end development background and limited experience in front-end development are able to catch up quickly. The error messages you might encounter along the way are usually clear and provide explanations on how to resolve the underlying problem. The hardest part may be finding the right libraries for all of the required capabilities, but structuring and developing an application is remarkably simple.
The framework itself is rich in topics to learn, starting from basic ones such as modules, dependency injection, decorators, components, services, pipes, templates, and directives, to more advanced topics such as change detection, zones, AoT compilation, and Rx.js. These are all covered in the documentation. Rx.js is a heavy topic on its own and is described in much detail on the official website. While relatively easy to use on a basic level it gets more complicated when moving on to advanced topics.
All in all, we noticed that the entry barrier for Angular is higher than for React. The sheer number of new concepts could be overwhelming to newcomers. And, even after you’ve started, the experience might be a bit rough since you need to keep in mind things like Rx.js subscription management, change detection performance, and bananas in a box. Error messages that are too cryptic to understand were often encountered.
Putting it Into Context
Each framework has its own set of capabilities, both with their good and bad sides. But this analysis has been done outside of any particular context, so a direct decision for your upcoming project is not cut and dry. To decide on that, you’ll need to review it from a perspective of your project. This is something you’ll need to do on your own.
To get started, consider answering these questions about your project and when you do, match the answers against what you’ve learned about the two frameworks.
- How big is the project?
- How long is it going to be maintained for?
- Is all of the functionality clearly defined in advance or are you expected to be flexible?
- If all of the features are already defined, what capabilities do you need?
- Are the domain model and business logic complex?
- What platforms are you targeting? Web, mobile, desktop?
- Do you need server-side rendering? Is SEO important?
- Will you be handling a lot of real-time event streams?
- How big is your team?
- How experienced are your developers and what is their background?
- Are there any ready-made component libraries that you would like to use?
If you’re starting a big project and you would like to minimize the risk of making a bad choice, consider creating a proof-of-concept product first. Pick some of the key features of the projects and try to implement them in a simplistic manner using one of the frameworks. PoCs usually don’t take a lot if time to build, but they’ll give you some valuable personal experience on working with the framework and allow you to validate the key technical requirements. If you’re satisfied with the results, you can continue with full-blown development. If not, failing fast will save you lot of headaches in the long run.
One Framework to Rule Them All?
Once you’ve picked a framework for one project, don't stay static with the same tech stack for upcoming projects. Don’t. Even though it’s a good idea to keep your tech stack consistent, don’t use the same approach every time just because. Before starting each project, take a moment to answer the same questions once more. At some point, a certain technology will just feel natural and right.