De EDB-blog
February 13, 2020

 

Deciding on a development framework for a new project is often done ad hoc, based on the available expertise and personal preferences of the developers involved in the project. However, the more rational approach for an enterprise would involve looking at specific criteria that the development framework should satisfy. The “general science” of making such a choice is simple and well-established. There are certain criteria to measure the performance of alternative options and the alternative with the highest cumulative performance is selected. One criterion may carry higher weight than another. Selecting the criteria and weighing them against each other is an art, and within the software development community, there are no generally accepted best practices on choosing the right software framework. 

With this context in mind, it’s important to note specific criteria when choosing a web framework. The most common criteria of choice include speed, maturity, stability, learning curve, and community support. The most prominent options considered in this post are React and Vue.js. Both options have high performance scores in respect to speed, maturity, learning curve, and community support. The choice between the two is not straightforward, and to rationalize the choice, we examine the frameworks in historical context of the evolution of Web UI. 

 

Comparing React and Vue

Web UI frameworks have consistently followed the MVC (Model View Controller) design pattern. Initially, React was marketed as the V in MVC, while in fact its designers were struggling to conceptualize React as a pure function that translates a UI state into a visual representation of UI. Vue.js had been the finest and cleanest specimen of the MVC design pattern. The difference between Vue.js and React is the difference between a clean MVC programming model and the emerging paradigm that conceptualizes Web UI as one pure function. With wider adoption, functional UI has emerged as a new paradigm that is a new way of thinking about UI.

Vue.js and React, the two key players, are now following this paradigm. Therefore, it is safe to say that functional UI has become the leading paradigm. Following the functional UI trend is a clear improvement for React as it lets React express its conceptual purity, which it had struggled to achieve, but the trend is not so good for Vue.js because it marks a departure from the clean MVC design that made Vue.js simple and understandable. React API is stable, but Vue.js API is in the process of evolution. Thus, React is currently on the forefront of the evolution of the UI paradigm while Vue.js is in the process of catching up. At the beginning of 2020, React appears to be the more suitable fit for a new enterprise-level project.

 

The Decision Problem

What UI framework would you choose for a new enterprise-level project starting in 2020? The choice has to be rational and encompass a range of criteria:

General Criteria

1. Expressive power and simplicity of API

2. Performance of the framework

3. Size of JS code—the footprint

4. Ease of learning

5. Good API design that facilitates maintainability

6. Testability

7. Availability of tools, libraries, and widgets

8. Community support on forums for help

9. Community or corporate support that ensures future framework developments

10. Stability of API

 

Company/Project-Specific Criteria

1. Fitness to specific project requirements

2. Availability of developers with framework experience already working in the organization

 

The problem is that there are many excellent frameworks to choose from. There is React, Vue.js, Angular, and new emerging players such as LitElement/lit-html. Which one is the best now? 

Actually, the more interesting question is: which one will be the best after one or two or three years? If this question sounds like a marginal one, then do you remember what happened to AngularJS a few years ago? Many enterprise projects written in AngularJS became technical debt even before they were completed because Google decided to create Angular 2. Or, remember Silverlight? Those who forget the past are doomed to repeat it. Understanding the history of web UI may help to predict where things are going and to make a safer choice, and making such a safer choice in 2020 is the subject of this post.
 

A Brief History of Web UI

In the beginning, Web UI was generated on the server, and the presentation logic, business logic, and data access code were mixed together. And there was chaos. From that chaos emerged the Model View Controller (MVC) pattern. As if some voice said: “Let the presentation logic be gathered in the View, let the business logic be gathered in the Model, and let the Controller separate the Model and View and serve as an intermediary between the two,” and it became so—various frameworks like Spring, Django, Rails, and ASP.NET MVC adhering to that pattern emerged, and it became the primary design pattern of Web UI. The MVC pattern enforced the important architectural principle of “Separation of Concerns” to ensure that data access, business logic, and presentation logic is handled in separate units.

In Web-based MVC frameworks, a controller would define a set of actions. Each action handles GET, POST, PUT, or DELETE web requests to a specific URL. To execute the action, the controller would query the Model to use business logic and data. Then, the Action would produce a set of parameters and use the parameters to render an HTML template. The View is an HTML template with free parameters. Rendering the View (template + parameters) would enable the generation of dynamic HTML pages. In this model, the state of Web UI was kept on the server in a session object, cache, database, or within the URL query string. Every update to the state of the UI would require a roundtrip to the server and a subsequent web page refresh. That was a time when the Web was still new and slow.

The invention of AJAX allowed asynchronous and partial web page updates. The successful AJAX frameworks still used the MVC pattern, only the action would not return the entire HTML page, but rather return a JSON object or a chunk of HTML, and that output would be used for a partial page update. With AJAX, the Web became a bit faster and better, but it was still not fast enough. Apps that required rich UI would rely on Silverlight and Adobe Flash.

Since JavaScript was adopted as part of the HTML 5 standard, things have changed dramatically. The assurance that there is a stable JavaScript API that every browser has to implement in the future led to the resurgence of a new UI framework relying on new Web standards. Silverlight and Adobe Flash became obsolete. There were companies that placed their bets on Silverlight right before Silverlight was discontinued. I helped one such company start using JavaScript for their Web UI. That was a time when architects and developers were not easily convinced that JavaScript could be as rich as Silverlight. The adoption of HTML 5 and new JavaScript frameworks have changed everything.

Most new JavaScript frameworks adopted the familiar MVC design pattern. It is as if the same voice said: “As it is above on the server so it should be below on the browser,” and it became so. In the browser, the MVC pattern works as follows: The Model defines the state of a Web Page. The Controller defines a set of Actions, typically JavaScript functions that update the DOM. The View is an HTML template + browser-based state kept in the Model. Often times, the template also contains bindings for Controller Actions to the browser’s events. The browser events then invoke the Controller’s Actions. The Actions can change the DOM using JavaScript. The Actions can also change the local state stored in the Model. The MVC pattern was adopted on the client side with several variations: Model-View-View-Model (MVVM) and Model-View- Whatever ( MV*). Knockout.js was the earliest MVC JavaScript library. Then, there were Backbone.js and Ember.js. AngularJS emerged a bit later and became the first successful Web UI library that enjoyed the widest adoption in Enterprise settings.

React was the second most widely adopted library after AngularJS. Today, React has the largest user base and is far ahead of other frameworks in terms of popularity. Initially, React was marketed as the V in MVC, but its designers were struggling to make React a pure function that translates the UI state into a visual representation of the UI. Unlike other popular Web UI frameworks, React did not have a separate template language. While other frameworks would extend HTML to introduce templating language, React represents the DOM in JavaScript and uses an extension of JavaScript called JSX to provide a friendlier description of the HTML DOM. 

In essence, React view is a tree of Components that are JavaScript objects that know how to render themselves. React also has functional components that are pure functions producing the HTML DOM as output given a set of parameters as input arguments. Before the introduction of React Hooks, these functional components were not allowed to have the component’s state owned by the component. With the addition of React Hooks, these functional components can do everything that regular React components can do, including having an internal component state. Functional React components are becoming the primary focus of React development, and it seems that future React developments will be based on these functional components.

React uses Virtual DOM, which is a JavaScript object that represents the DOM tree. When making a sequence of updates to a Web page, React updates the Virtual DOM and then matches the real DOM with the Virtual DOM. This update strategy made React faster than its competitors. Also, with Virtual DOM, the actual rendering can be separated from the Virtual DOM, and renderers different from the Web browser can be supported. This enabled such technologies as headless rendering on the server and rendering on mobile devices. React Native is possible because of the Virtual DOM. There is a catch: To use all the advantages of the Virtual DOM, all DOM updates must be controlled by the Virtual DOM. The use of jQuery together with React (or Vue.js) is actively discouraged because jQuery accesses the browser DOM directly.

The proponents of React JSX were complaining about the fact that in MVC frameworks HTML templates and controllers are kept in separate files, and they would say that such a separation is not a separation of concerns but merely a separation of technologies. There was another group that believed that HTML templates as they were used in MVC frameworks are better and have a cleaner design compared to JSX. HTML templates are friendly to UX designers, as some are not proficient in JavaScript but know HTML well. Vue.js owes its existence to these considerations. It offers familiar HTML templates to former AngularJS developers who are not happy with JSX. It also gives the opportunity to keep JavaScript controllers and templates in the same files, exactly as the proponents of JSX wanted. Vue.js also uses the Virtual DOM and is as fast as React. Vue.js was envisioned as both a better Angular and a better React.

 

State Management and the “Quest for a Single Source of Truth”

Since the beginning, managing a Web UI state has been one of the most important design concerns. In traditional MVC design, the state is stored in the Model, and it worked well in most cases. One problem encountered by Facebook developers is that MVC does not scale when the state is spread between different models. Jing Chen, a software engineer at Facebook, proposed the Flux design pattern, which enforces unidirectional information flow between the UI and State. The Flux pattern became the foundation and inspiration for the most popular React state management tool, called Redux, also developed by a Facebook engineer, Dan Abramov. 

 

 

Vue.js followed the trend with Vuex, which is essentially an adaptation of Redux. Angular 2+ also has a similar state management tool called NgRx which is also a kind of Redux implemented based on the RxJS library using Reactive Programming patterns.

Redux and its derivatives work as follows: 

(1) The Store is one and only one Model that stores all of the UI State. The Store is a “Single Source of Truth” for the entire UI State. When UI is a Single Page App, the Store can grow very large. 

(2) All changes to the State (Store) are made by emitting Actions. 

(3) The changes to the State are computed with pure functions called Reducers. 

The signature of a reducer is as follows:

Reducer(State, Action) => NewState

 

While the State tree stored in the Store is one, there can be many Reducers charged with the responsibilities of handling various specific branches of the State tree. Redux struggles with functional purity and enforces the immutability of the State, requiring reducers to always return a new State. Vuex allows state mutability. Vuex also relaxes the “Single Source of Truth” principle and allows it to spread the State among different modules.

The Redux/Flux pattern offers several advantages:

1. As Reducers are pure functions, the UI logic can be easily tested.

2. The Redux pattern scales well as the application grows.

3. As State changes are pure functions, they can be rolled back. This allows developing such things as a “Time Traveling Debugger” (React and Redux dev tools have such a thing).

 

Some cross-cutting UI concerns do not easily fit into the Redux pattern—e.g., What about the browser history state and the transient UI side effects such as a waiting sign indicating that the UI is waiting for the result of the query made to the backend? In the early days of Redux, many influential people at Facebook liked the Flux/Redux pattern very much, and they waged “a struggle for ideological purity” to enforce that pattern across all UI concerns of React applications using it in some way. As a result of this push, newer versions of React Router can store the browser history state in the Redux Store. To handle side effects (such as animations or requests to backend API), Redux-Sagas were introduced. Overall, these were very valuable improvements; however, in the process, some very complex high boilerplate programming patterns were also introduced and widely used by React developers. 

It is safe to say that Redux or its equivalent is used as a primary state management pattern for modern UI applications. Here is a resource on State Management with Redux vs Vuex. The post also indicates that Vuex is simpler than Redux, which brings us to the following point.

 

Vue Was Better than React in 2017

Vue.js was introduced as both a better React and a better Angular, and many elements of the Vue API have much less boilerplate. Vuex also has a bit simpler API compared to Redux. While both frameworks have about the same performance and browser footprint (Vue.js is slightly better), both frameworks enjoy wide community support, tooling, widget libraries, and the assurance of future development. Vue.js wins over React in simplicity of use and absence of boilerplate code. Vue.js enjoyed a very fast adoption rate because of the very enthusiastic user community. For developers who learned to appreciate AngularJS’s templating system and fastest learning curve, Vue.js was a clear framework of choice.

 

React Hooks and the Functional UI Revolution

UI is a function of State: UI = F(State). This is the point that many React developers have been trying to make.  Therefore, it would be preferable to express UI as a pure function.  

The officially recommended approach to thinking in React is to start from the abstract state that UI has to render and to design the UI as a hierarchy of components that each translate a small part of the global State into a visual representation. Wouldn't it be nice if those UI components were pure functions? React had pure functional components, but until the introduction of React Hooks, their capabilities were limited. They were not allowed to have their internal state and were only allowed to render parameters passed from parent components. After the introduction of React Hooks, the entire React UI could be built from pure functional components, and everyone seems to love this approach. 

React Hooks is a very good architectural novelty, and many other frameworks wanted to adopt the pattern and hop onto the functional UI bandwagon—e.g., the LitElement project got its functional version, and the Vue.js project came up with the Vue 3 Functional API proposal. 

 

2020 is a Good Year for React  

The reaction to the Vue 3 API proposal was very controversial. Some negative comments on the proposal sounded as follows: “If you want to make React out of Vue.js, why not simply use React?” Consider the title of this blog post, “Vue’s Darkest Day.” 

Although the author argues that the negative reactions were in the minority, it is clear that the enthusiasm for Vue.js is not as strong. And it is not about Vue.js as such, it is about the paradigm shift to functional UI, which was a natural incremental improvement for React and a paradigm-breaking change for Vue.js. The much-loved templating system of Vue.js does not express the idea that “UI is a function of State” as clearly as React’s approach to rendering HTML using JSX. Since the future Vue 3 API will have a paradigm-breaking change, it is not a good time to base new development on Vue.js. 

An incremental improvement to React that happened during the last two years has dramatically simplified patterns and best practices used by React developers. Other than empowering functional UI components, React Hooks offer elegant patterns for code reusability. They also offer far simpler coding patterns for solving many common problems. Solutions for a wide range of concerns, such as maintaining State, fetching data from backend API, memoizing UI state variables, controlling side effects, and much more have been packed in the form of React Hooks and made available for React developers on Github.

Other frameworks are trying to duplicate what has already been accomplished by the React community. Eventually, they will get it, but it will take time. In 2020, React seems to be the web framework of choice for a new project.

 

Click here for a free trial of an enterprise-class data management platform with flexible deployment options. 

 

 

sergey.krivov's picture

Sergey is a Lead Software Engineer at EnterpriseDB. He has 20+ years experience developing software with various languages and frameworks. Since 2013, Sergey worked on the Web UI side and witnessed the evolution of modern JavaScript frameworks.