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:
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
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
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.
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.