The author of the material, the translation of which we are publishing today,
believes that
Hyperapp is a worthy alternative to such web frameworks as
React or
Vue . He says that the reason for this statement was that he found out that Hyperapp is easier to learn than these two frameworks. His idea was criticized, as it seems that it is based solely on his opinion, and this approach simply does not allow other frameworks to show their strengths. This article is aimed at an objective analysis of Hyperapp, React and Vue, conducted on the basis of simple examples demonstrating their capabilities, and based on the results of their tests.

Example number 1: application counter
Implementing an application counter is probably one of the most frequently used examples in reactive programming. It is extremely simple and straightforward:
- We need a variable
count
, which will store the value of the counter. - We will need two methods to increment and decrement the
count
variable. - A mechanism is required to output the value stored in
count
and present it to the user. - We need two buttons tied to the appropriate methods, allowing the user to affect the variable
count
.
Here is an implementation of this example using the frameworks in question.
')
â–ŤReact
import React from "react"; import ReactDOM from "react-dom"; Class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 0}; } down(value) { this.setState(state => ({ count: state.count - value })); } up(value) { this.setState(state => ({ count: state.count + value })); } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick = {() => this.down(1)}>-</button> <button onClick = {() => this.up(1)}>+</button> </div> ); } } ReactDOM.render(<Counter />, document.querySelector("#app"));
â–ŤVue
import Vue from "vue"; new Vue({ data: { count: 0 }, methods: { down: function(value) { this.count -= value; }, up: function(value) { this.count += value; } }, render: function(h) { return( <div> <h1>{this.count}</h1> <button onClick={() => this.down(1)}>-</button> <button onClick={() => this.up(1)}>+</button> </div> ); }, el: "#app" });
â–ŤHyperapp
import { h, app } from "hyperapp"; const state = { count: 0 }; const actions = { down: value => state => ({ count: state.count - value}), up: value => state => ({ count: state.count + value}) }; const view = (state, actions) => ( <div> <h1>{state.count}</h1> <button onclick={() => actions.down(1)}>-</button> <button onclick={() => actions.up(1)}>+</button> </div> ); app(state, actions, view, document.querySelector("#app"));
â–ŤAnalysis
If you are not familiar with these frameworks, or at least one of them, then you will probably encounter something incomprehensible here. So let's break down this code.
- When using all three frameworks, there are
import
commands at the beginning of the application code. - React uses an object-oriented paradigm. Here a class is created for the
Counter
component. Vue goes the same way. A new instance of the Vue
class is created here, information is sent to it. And finally, Hyperapp uses the functional paradigm, independent view
, state
and actions
are used here. - If we talk about the variable
count
, in React it is initialized in the component's constructor, and in Vue and Hyperapp it is a property of, respectively, data
and state
objects. - If you go further in exploring these applications further, you will notice that React and Vue use very similar methods to interact with the variable
count
. In React, to change the state of an application, the setState
method inherited from React.Component
. In Vue, the value of this.count
changed directly. Methods in Hyperapp are written using ES6 switch function syntax. Among the frameworks in question, he is the only one who uses this, since React and Vue are forced to use the keyword this
in their methods. Hyperapp methods, on the other hand, require that, as an argument, they be passed an object with an application state. This means that they can most likely be reused in different contexts. - The part of the application that is responsible for displaying data on the page looks almost the same in all three examples. The peculiarity of Vue is that when using this framework, it is necessary to transfer the function
h
to the rendering subsystem. In Hyperapp, instead of onClick
, onclick
used, and the count
variable is accessed differently than in React and Vue, which is due to the peculiarities of how application state storage is implemented in each framework. - And finally, all three frameworks use a binding to the
#app
element. In each of them, this operation is performed differently. It should be noted that in Vue this operation looks the simplest and most understandable and gives the developer a more flexible design, working with the element selector, and not with the element itself.
â–Ť Conclusions
If you directly compare the code that solves the same problem, written using all three frameworks, it turns out that Hyperapp, for the implementation of the counter application, requires the least amount of code lines, and this is the only framework that uses the functional approach. However, the amount of code written using Vue, if we count the number of characters, is slightly less, and the use of the element selector in it looks very good. React-application code seems to be the longest, but this does not mean that it is much more difficult to understand than code written to work with other analyzed frameworks.
Example number 2: work with asynchronous code
It is possible that in practice you will have to deal with asynchronous code. One of the most common asynchronous operations is to send a request to a certain API. For the purposes of this example,
the JSONPlaceholder API is used , containing conditional data and issuing a list of publications. Here is what we are going to do here:
- Let's save an array for placing
posts
in it in the application state. - Call the
fetch()
method using the appropriate method, specify the URL we need, wait for the data, parse the resulting JSON code, which is an array of objects, and finally update the posts
variable by writing the received data to it. - Let's display a button on the page that calls the method that loads the list of publications.
- Let's output a list of
posts
from posts
using keys.
Consider the code that implements the above scheme of action.
â–ŤReact
import React from "react"; import ReactDOM from "react-dom"; class PostViewer extends React.Component { constructor(props) { super(props); this.state = { posts: [] }; } getData() { fetch(`https://jsonplaceholder.typicode.com/posts`) .then(response => response.json()) .then(json => { this.setState(state => ({ posts: json})); }); } render() { return ( <div> <button onClick={() => this.getData()}>Get posts</button> {this.state.posts.map(post => ( <div key={post.id}> <h2><font color="#3AC1EF">{post.title}</font></h2> <p>{post.body}</p> </div> ))} </div> ); } } ReactDOM.render(<PostViewer />, document.querySelector("#app"));
â–ŤVue
import Vue from "vue"; new Vue({ data: { posts: [] }, methods: { getData: function(value) { fetch(`https://jsonplaceholder.typicode.com/posts`) .then(response => response.json()) .then(json => { this.posts = json; }); } }, render: function(h) { return ( <div> <button onClick={() => this.getData()}>Get posts</button> {this.posts.map(post => ( <div key={post.id}> <h2><font color="#3AC1EF">{post.title}</font></h2> <p>{post.body}</p> </div> ))} </div> ); }, el: "#app" });
â–ŤHyperapp
import { h, app } from "hyperapp"; const state = { posts: [] }; const actions = { getData: () => (state, actions) => { fetch(`https://jsonplaceholder.typicode.com/posts`) .then(response => response.json()) .then(json => { actions.getDataComplete(json); }); }, getDataComplete: data => state => ({ posts: data }) }; const view = (state, actions) => ( <div> <button onclick={() => actions.getData()}>Get posts</button> {state.posts.map(post => ( <div key={post.id}> <h2><font color="#3AC1EF">{post.title}</font></h2> <p>{post.body}</p> </div> ))} </div> ); app(state, actions, view, document.querySelector("#app"));
â–ŤAnalysis
Let us analyze this code and compare the three frameworks under study.
- As in the previous example, storing the state of the application, outputting data, and connecting to the page element in all three frameworks are very similar. There are the same differences, which we have already mentioned above.
- Loading data with the
fetch()
function is quite simple; it works as expected in all frameworks. The main difference here, however, is that Hyperapp supports performing asynchronous operations a bit differently than other frameworks. Instead of modifying the state directly, inside an asynchronous action, this action triggers another, synchronous action that receives data and converts it into a suitable format. This makes the core of the application more functional and better suited for dividing into small pieces that are potentially suitable for reuse. This approach, in addition, helps to avoid some of the problems inherent in nested callbacks that may arise in situations similar to those considered. - If we talk about the size of the code, the Hyperapp application again needs fewer lines of code to achieve the same goal, but the code on Vue looks more concise, and if you count the number of code symbols, it is shorter than the other options.
â–Ť Conclusions
Performing asynchronous operations turned out to be equally simple in all frameworks. Hyperapp can lead a developer to write more functional and modular code when working with asynchronous actions, but the other two frameworks do an excellent job with their task, and, in this regard, give the developer a choice.
Example 3: list item component for a To-Do application
Probably, To-Do-applications are the most famous example in the field of reactive programming. Apparently, something similar is implemented using almost every existing framework. Here we will not implement the entire application. Instead, we will focus on a simple, stateless component in order to explore the capabilities of the frameworks under study to create small building blocks of web applications suitable for reuse.
Consider the implementation of the component with the use of the frameworks under study. In this example, however, we will expand the considered code variants by considering the React-component written in the functional style.
â–ŤReact (functional style)
function TodoItem(props) { return ( <li class={props.done ? "done" : ""} onclick={() => props.toggle(props.id)}> {props.value} </li> ); }
â–ŤReact
class TodoItem extends React.Component { render () { return ( <li class={this.props.done ? "done" : ""} onclick={() => this.props.toggle(this.props.id)}> {this.props.value} </li> ); } }
â–ŤVue
var TodoItem = Vue.component("todoitem", { props: ["id", "value", "done", "toggle"], template: '<li v-bind:class="{done : done}" v-on:click="toggle(id)">{{value}}</li>' });
â–ŤHyperapp
Pay attention that Hyperapp also uses the functional style.
const TodoItem = ({ id, value, done, toggle }) = ( <li class={done ? "done" : ""} onclick={() => toggle(id)}> {value} </li> )
â–ŤAnalysis
- React, in terms of coding patterns, is the most flexible framework. It supports functional components, as well as components designed in the form of classes. In addition, React, in its standard form, supports Hyperapp components.
- Hyperapp also supports functional React components. This means that when working with Hyperapp and React there is plenty of room for experimentation.
- Vue takes the last place in this test. It has a rather strange syntax that is not easy to understand immediately, even for those who are familiar with React or Hyperapp.
- If we talk about the length of the code, then all the examples have very similar sizes. The only thing that can be noted here is that the code on React, in one of the options, turned out to be a bit more voluminous than in the other.
â–Ť Conclusions
In order to get used to Vue, it takes some time, as its templates are slightly different from the templates of the other two frameworks. React is extremely flexible, it supports various approaches used to create components. At the same time, everything is very simple in Hyperapp, and it, moreover, is compatible with React, which allows, if necessary, at some stage of the project, to change the framework.
Comparing Component Life Cycle Methods
Another important consideration that influences the choice of the framework is the events of the life cycle of components it supports, which you can subscribe to and which can be processed according to the needs of the developer. Here is a table based on an analysis of the API of the systems under study.
Event
| React
| Vue
| Hyperapp
|
Initialization
| constructor
| beforeCreate, created
| - |
Mounting
| comoinentDidMount
| beforeMount, mounted
| oncreate
|
Update
| componentDidUpdate
| beforeUpdate, updated
| onupdate
|
Unmounting
| componentWillUnmount
| - | onremove
|
Destruction
| - | beforeDestroy, destroyed
| ondestroy
|
â–ŤAnalysis
Here is what you can understand by analyzing this table:
- Most of the life cycle hooks are in Vue. With their help, the programmer has the opportunity to handle everything that happens with the component, either before calling the corresponding event or after. This can be useful for managing complex components.
- The React and Hyperapp lifecycle hooks are very similar, although React combines the processing of events that occur when a component is unmounted and destroyed, and Hyperapp does the same with component creation and mounting events. Both provide the developer with a sufficient number of opportunities for handling life cycle events.
- Vue does not handle the unmount event (as far as this can be understood by analyzing the framework API), instead relying on the hooks associated with the destruction of the component. React does not handle a component kill event, allowing only the component unmount event to be processed. Hyperapp does not offer hooks to handle a component creation event, instead relying entirely on a mount event. Depending on your needs and experience, these differences should be taken into account when designing an application, taking into account the possibility of processing events of the life cycle of components.
â–Ť Conclusions
In general, it can be noted that methods for handling events that occur during the life cycle of components support all frameworks. These methods will solve many problems. All three frameworks offer hooks for all kinds of events, but there are minor differences between them, the source of which can be internal features of frameworks and differences in their implementation. Perhaps Vue in this area is one step ahead of other systems, offering a more detailed event handling system, allowing you to handle life cycle events, either before or after they occur.
Framework Performance Comparison
In addition to the ease of use of the framework and the programming techniques used to work with it, many developers are seriously concerned about the performance of frameworks, especially for fairly complex applications. A valuable source of information about the performance of various frameworks is the
js-framework-benchmark project.
Therefore, take a look at the test results of React, Vue and Hyperapp.
â–ŤWork with tables
Here are the results of testing frameworks for working with tables. The indicator in the cells of the table corresponds to the duration of the operation ± standard deviation. In parentheses is the result of dividing the resulting indicator by the best indicator.
Analysis
- Operations in which data keys are not used (non-keyed) are much faster than operations in which keys are used (keyed).
- The fastest of all six options considered was the one that uses React without using keys, which shows impressive performance in all tests.
- If you compare Vue and React when working with keys, then Vue has a slight advantage here. At the same time, if we compare React and Vue in variants where the keys are not used, Vue shows significantly lower performance than React.
- Vue and Hyperapp, as you can see from the results, have some difficulties with the test, which partially updates the table (partial update), and React shows itself well, probably due to some optimization aimed at accelerating such operations.
â–ŤDownload, launch, code sizes
Here is a table with the results of a study of indicators related to the launch speed of the framework, its size, and its use of the main thread.
Analysis
- The Hyperapp code was the smallest among the studied frameworks. The React and Vue code is about the same size.
- Hyperapp needs the least start time. The reason for this, of course, is the small code size of the framework and the minimalist approach to designing its API.
- Vue, if we talk about the time it takes to launch the framework, is a little faster than React.
â–ŤWorking with memory
Now consider the results of memory allocation tests.
Analysis
- Hyperapp is the most undemanding framework in terms of memory consumption.
- In general, it can be noted that all frameworks do not consume much memory. This suggests that they, on modern computers, will work approximately equally.
â–Ť Conclusions
If, when developing a certain project, you need to achieve maximum performance, you should understand, firstly, what application you are developing, and secondly, clearly identify the needs of this application. If you put together the performance analysis of all three frameworks, you get the feeling that Vue and React are better suited for more complex applications, and Hyperapp shows itself better on smaller-scale applications that need to process less data that requires faster startup. and who may need to work on not the fastest computers.
However, it is worth remembering that the performance tests used here are far from real life, from a certain average scenario. Therefore, having tested and compared them on a real project, you can see other results.
Additional Notes
It should be noted that the comparison of web frameworks may resemble something like the comparison of apples with oranges. Here are some other considerations regarding React, Vue and Hyperapp that may be useful when choosing a specific framework for a certain project:
- React avoids the problem that neighboring JSX elements must be wrapped in the parent element, introducing the concept of fragments — elements that allow you to group a set of descendant elements without adding additional nodes to the DOM.
- React makes available to the developer components of a higher order , while in Vue, for the purpose of re-using the functional components, mixins are used.
- Vue more fully exploits the concept of sharing responsibility, sharing the structure and functionality of the application using templates .
- Hyperapp, when compared to React and Vue, looks like a system that provides a lower level API. The code of Hyperapp applications is shorter, it gives more flexibility, which can be useful in cases where the developer may want to do his fine tuning and research of its internal mechanisms.
Results
The author of this material believes that if you have read this far, then you have already formed an understanding of which of the frameworks studied here is best suited to your needs. In the end, we didn’t talk about which of the frameworks is the best, but rather which of them is best able to show itself in various situations. As a result, the following general conclusions can be made:
- React is a very powerful tool, it has a large community of developers around it, which, if you have any problems, may well help you in solving them. This framework is not so difficult to master, but in order to master it perfectly, it will take a lot of time. , React — , .
- Vue , - JavaScript-, — . React, , , , React - . Vue , , , , React.
- , , Hyperapp — , , — . , React Vue, . , . , Hyperapp, , , , Hyperapp-, . , , Hyperapp, , , , React Vue, .
Dear readers! -?
, - 10% :)