In this article we will take a dive into the world of the two prominent frontend frameworks, in order to compare them and to facilitate a choice from multiple perspectives. We will take a look at a Hello World application written in both frameworks, explore their philosophies, and project their respective advantages and disadvantages on a larger scale. We will use both frameworks with the TypeScript language, assuming a modern web-friendly IDE such as VS Code.
Both frameworks are based on the idea of incrementally reconstructing the structure (DOM) of the web-page that is shown to the user via the browser through a comparison algorithm (often shortened to diff), in order to re-draw only the elements that have changed, given that re-drawing is a slow process and if we do it too much we risk ruining the user’s experience. Unfortunately, such a diff algorithm itself can be very expensive: in the worst case, a tree with n nodes will require a time proportional to the square of n (a complexity of O(n2)). A typical web-page will contain lots of node, tens to hundreds at the very least, leading to a potential comparison which is even slower than re-drawing everything from scratch. In order to mitigate this problem, both frameworks try to reduce this complexity so that we only need to check all elements once. This makes a gigantic difference in performance, and makes such an approach decidedly feasible.
Angular focuses on changes on the data that underpins the page and provides the content to render, whereas React focuses on changes in the structure of the page itself.
Let us now quickly dive into the way a tiny sample would be structured in both frameworks.
In angular, we quickly notice that the standard way of structuring an application is in components. Each component isolates a piece of logic for showing and managing changes to a given data structure. Components are split into three main chunks, following conventional web-development wisdom:
- a CSS file to style the component;
- a TypeScript file to manage the logic of the component (the controller);
- an HTML file to manage how the component is rendered (the view).
Moreover, one or more files will define the underlying data structures that the application will manage (the model).
Let us now extract a tiny excerpt from a popular Angular tutorial just to give a superficial impression. The tutorial is the Hero application, which manages a list of heroes. The relevance of this tutorial is that it has been followed many times by beginner developers, and is a bit of the rock-solid foundation for many Angular projects.
A model in Angular simply specifies the properties of an entity in TypeScript. An example of such a model would be the representation of the Hero object itself:
Multiple type definitions will feature in one (or, more likely, more) different model files.
A controller is just a class which offers a series of properties (in this case selectedHero and heroes), and methods which are invoked in relation to some user event:
A type defined among the models may be used in multiple controllers, in many cases also in conjunction with other such types.
The very last mile is to render something from a controller. The view is expressed as regular HTML, plus a series of attributes which are specific to Angular and have nothing to do with standard HTML. The view binds values taken from the controller onto the page, in either one-direction (usually to display data) or two-directions (to both display data, and allow for input to change values in the controller right away):
Notice how the binding is expressed in two different formats: one, by using double curly brackets (mono-directional), and one with [(ngModel)] (bi-directional).
Also notice how directives such as *ngFor allow us to perform features such as iteration over a collection. This means that the HTML “format” that Angular supports and understands is significantly extended in order to also be able to manipulate and manage reasonably complex data structures and their translation into something renderable, all through specific attributes.
React models, just like Angular models, are simply a series of TypeScript type definitions. For example, a graph renderer could feature the following types in its model:
React view and controller
React conflates view and controller together. A React component encapsulates both the logic and the rendering of some data, known as a component’ props. The component takes as input its props, which contain the data to render, and simply returns the appearance associated with these props in the form of a JSX.Element, which is a declarative description of the desired shape of the DOM:
The properties contain both data and callbacks. The data is read-only, and is read by the component in order to produce the DOM to be rendered. Data is inlined with curly brackets, for example by writing:
The callbacks, when invoked, trigger actions in the parent components up until the root component, known as a container, will perform a write operations and write to the application state. We see, in the code above, that
passes the callback props.save to editArea, in order to invoke the saving callback whenever the user types something into the editor.
Eventually, a container, which is the same as a component, but implemented as a stateful class, will invoke setState in order to write changes to the state of the application.
More vs Less
It is clear from the example that the calling surface of Angular is much bigger. Angular requires a developer to learn a framework (the onInit class) with lots of specific little things such as nglf, ngFor, etc. in order to bind data to the renderer.
Data binding in Angular uses an imperative style of programming. This is very familiar to many developers, and matches the expectations of those who learned to program on frameworks such as WinForm and similar. Data binding is, at least historically seen, a golden standard.
The use of data injected directed into renderers, and the calling of events in order to trigger changes, is more complex as it requires mastering anonymous functions and in general concepts typical of functional programming in order to be able to perform simple tasks, but the flow of data is very predictable and as such the application will contain less data races and other complex-to-debug issues.
Static typing and IDE integration
React uses much more language features. This means that constructs like *ngFor, which are extensions that are dynamically typed (and might thus fail at runtime!) are simply expressed as standard language constructs in React. The net result is simpler code, that uses standard software engineering instead of a mixture of standard code constructs and various Angular extensions.
This also has impact on the amount of help the compiler (and the IDE) will be able to offer us while typing code. All sorts of React code is simply recognized by the IDE as valid TypeScript code. This means that every feature of React will be aided by the Intellisense/code completion facilities of the language. Instead of the developer having to learn a lot of constructs by heart, or having to rely heavily on testing, it will be possible to ask the IDE for as much help as it can possibly give us:
Community and popularity
The community and popularity of the two frameworks is now quite different. Looking at the number of people actively downloading React from npm, we see (at the time of writing) 2.4 million downloads in the last week alone. Popular Angular packages are also quite popular, but significantly less. For example, angular/core featured 650 thousand download last week. This shows great relevance, but also hints at a smaller and less vibrant community.
Packages dependent on React are also far more (23 thousand) versus those dependent on angular/core (6 thousand).
In all cases, both frameworks are more than evidently very popular and relevant, but React quite more.
In conclusion, both React and Angular are powerful, popular frameworks. Angular is perhaps closer to the traditionally imperative/object-oriented, slightly larger philosophy of data binding and heavy tooling, whereas React is a bolder innovator in its adoption of functional programming and elegant minimalism.
Both frameworks are vibrant, and support fundamental modern features such as the ability to deploy an application as a mobile native application, and to integrate with most important modern functionality of browsers and API’s.
Betting on either of the two frameworks would be a safe and reasonable choice. Given the slightly higher popularity of React, and its elegant and expressive design, we have chosen for it, and enjoy every day of its power and simplicity in order to create fantastic single page applications for our customers.
It is an exciting time to be a web developer.
Schrijf je in voor onze nieuwsbrief en laat ons jouw gids zijn in een complexe digitale wereld.