ApriorIT

Every team developing a web application faces the problem of choosing the most suitable technology for their project. It’s easy to get lost in the variety of web frameworks, as new frameworks constantly appear and existing frameworks are updated and transformed beyond recognition.

Choosing a technology that perfectly meets your project needs will boost your team’s productivity and enhance your application’s capabilities; choosing the wrong technology will harm them.

In this article, we compare three JavaScript frameworks: Knockout, Vue, and React. All of them are lightweight frameworks that are easily integrated into a project, so we’ll focus on their key features, third-party integrations, and performance. This article will help you understand which JavaScript framework to choose for your project.

Contents:

Learning curve

Overview of key framework features

     Knockout

     Vue

     React

Third-party integration capabilities

Comparing performance

Conclusion

Learning curve

One of the most important non-technical criteria for choosing a framework is the time required by the development team to study the new technology. This indicator can be measured using a learning curve — the correlation between experience and knowledge gained and time spent studying. According to our experience, a comparison of the Vue.js, React, and Knockout learning curves looks like this:

Learning curve for Vue, React, and Knockout

As you can see, all of these frameworks are easy to learn but hard to master. 

Building the first application with Knockout is challenging because you’ll need to write lots of custom adapters for third-party libraries. Development becomes easier once you finish writing the infrastructure code.

Vue is somewhat similar to Angular, so it’s easier for Angular developers to study this framework. Vue documentation clearly explains how your application should look and how it should be structured, and there aren’t a lot of hidden challenges as you start development.

React is challenging to understand initially, as its internal features and style of writing components differ from other JavaScript frameworks.

Related services

Custom Web Application Development Services & Solutions

Another important factor influencing a developer’s learning speed is the support of the development community. A framework’s community helps developers quickly find answers to questions that aren’t covered by the documentation and provides real-life examples of how to use the framework.

Vue and React were ranked the second and third most loved frameworks in the 2020 Stack Overflow Developer Survey. These frameworks have very supportive communities: their forums and blogs are packed with information. The Vue and React communities constantly search for new development approaches and create additional libraries, and the Vue and React development teams regularly release fresh versions of the frameworks.

Knockout seriously loses to Vue.js and React in terms of the community. The peak of its popularity has long passed, and Knockout isn’t even on the list of the most loved frameworks anymore. However, there are a lot of old articles and forum threads that answer common questions about it. New versions of Knockout are rare, so it doesn’t keep up with current development trends.

Overview of key framework features

Supported features is one of the key considerations when choosing a framework. The most significant differences between Knockout, React, and Vue are the following:

 

Knockout

Vue

React

Architectural pattern

Model–View–ViewModel (MVVM)

Model–View–Presenter (MVP)

Model–View–Controller (MVC) or MVVM

Data binding

Two-way data binding

Two-way data binding

One-way data binding

Templates

Plain HTML

Plain HTML

.jsx

Routing

No, just custom libs such as Pager.js

Provided separately in vue-router and other libs

Provided separately in react-router and other libs

DOM updates

Real DOM

Virtual DOM

Virtual DOM

Nested children event handling

Needs to be handled manually

Supported

Needs to be handled manually

Lazy module loading

None

None, but easy to implement

Provided with react.lazy() function

Let’s take a closer look at the features of each framework.

Knockout

This framework implements the MVVM pattern and provides all necessary functionality for building dynamic pages using the component approach or directly binding the model to the markup. In addition, to use data binding, it’s enough to connect one file with a JavaScript library to your project.

Unfortunately, there are some significant downsides to Knockout. This framework requires developers to create lots of View models using ko.Observable constructions, or to convert all existing models to this type. This sometimes clutters the code, giving us models similar to this one:

function Person(){
   this.FName = ko.observable();
   this.LName = ko.observable();
   this.Age = ko.observable();
   this.Benefits = ko.observableArray();
   this.FullName = ko.computed(function()
            {
                return this.FName() + “ ” + this.LName();
            }, this);
}

You can see several issues in the code above. All arrays must be marked with ko.observableArray. In addition, any object that turns into an observable becomes a function and must be accessed using operator (). This can cause a lot of errors in the code. When you don’t know if a field is observable or not, you need to constantly check whether the field is a function so you know how to access it.

Because of the MVVM pattern, you have to place any actions performed on the model inside that model, which violates the single-responsibility principle. Additionally, you can’t separate models, since you can attach a model only to one part of a markup. The ko.applyBindings construct binds the model to the markup. Keep in mind that if you call this function several times in a row, the model will not rebind but will simply return an error.

To track changes in field states, Knockout uses standard Document Object Model (DOM) events and can easily erase your events — or you can accidentally mix Knockout events with yours. In one of our Knockout-based projects, this feature caused a lot of hard-to-detect errors. Also, Knockout uses the real DOM to update markup. Because of this, the framework rewrites markup completely if the developer updates it.

Knockout copes with basic tasks like providing two-way data binding to the markup, but it doesn’t support modern features like routing and lazy loading.

Read also:
Angular 9 and 10: Overview of the Key Features

Vue

Vue implements the MVP pattern, which means that logic and actions with the model are embedded within this model and can be removed to another entity. This pattern helps to separate data from operations on it by moving those operations to other objects and files. Vue supports computed properties, which can also be moved to a separate entity.

Similar to Knockout, Vue allows you to work with the model and view and directly bind the model to the markup using the Vue object. In this case, you can use absolutely any model and it doesn’t need to be changed in any way. Vue also supports two-way data binding that updates data in one element when another element is updated.

Vue works with a virtual DOM. Any changes in markup are first made to the virtual DOM, then displayed in the real DOM using comparison mechanisms. That is, when elements are changed, Vue doesn’t rework the DOM completely but updates only the changed properties.

Let's look at a sample of code that demonstrates a non-component approach to using Vue:

this.globalVue = new Vue({
    el: '#main-form',
    data: this.business.model,
    methods: {
        Do: function() { ... }
    }
});
 
class Business {
    public model: MyModel;
}
 
<form id='main-form'>
    <input v-model="Name" id="name" class="form-control"/>
    <button v-on:click="Do">Submit</button>
</form>

As you can see, the code is pretty straightforward. We declare a Vue object with data, methods, and template properties, and then we can use it on our markup.

Now let’s consider the component approach. Vue supports child components by default, passing data to them and receiving events in the parent component. Here’s an example of the simplest Vue component:

Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">Click count — {{ count }}</button>'
})

In addition to common web framework features, Vue has a lot of support packages and libraries such as routing and Vuex — Vue’s implementation of the Flux architecture — to provide developers with additional functionality.

React

React focuses on the “View” part of the MVC and MVVM patterns. On top of that, by using modules like redux-saga, developers are free to choose the architectural approach they consider most appropriate for their project. This React capability adds flexibility to the development process. However, integrating React into an existing project is more complicated compared to integrating Knockout or Vue, since you can't partially migrate a page to another framework.

Integrating React to an existing project is more complicated compared to integrating Knockout or Vue, since you can’t partially migrate a page to another framework.

React has a tricky implementation process because it works with .jsx files that combine JavaScript code and HTML markup. A browser doesn’t know how to process such files, so they must be converted to standard formats. To do this, you need one of many available engines. In our React-based projects, we set up the Babel engine.

Because of the long preparation time, starting development with React takes more time than with other frameworks. Here’s an example of a simple React component:

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }
 
  getSnapshotBeforeUpdate(prevProps, prevState) {
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }
 
  componentDidUpdate(prevProps, prevState, snapshot) {
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }
 
  render() {
    return (<div ref={this.listRef}>{/*...contents... */}</div>);
  }
}
 
ReactDOM.render(<Car/>, document.getElementById('root'));

As you can see, the style of React code is different from Vue and uses object-oriented features. You can write components as functions that return markup, but presenting a component as a class is more convenient for some developers. However, for backend developers, mixing markup and project logic may seem like a violation of the single responsibility principle. You can also notice that the markup in the render method is written as structured HTML code and isn’t quoted due to the properties of the .jsx format.

You can only use the component approach when developing the front end of the project with React. It’s impossible just to attach the model to the markup — there should always be at least one global component in the project. The major difference between Vue.js and React is that the latter supports only one-way data binding. If a project needs two-way data binding, developers have to support it manually using events and callback functions. Also, there’s no built-in event handling mechanism for child components.

Similarly to Vue.js, React works with a virtual DOM instead of the real DOM. This allows the framework to update markup quickly. To improve application management, many web developers combine React with the Redux architecture, which is an evolution of Flux. Also, React has many independent packages and libraries to support modern web development features like routing and lazy module loading.

Read also:
Single-Page Apps: Advantages, Pitfalls, and Best-for Suggestions

Third-party integration capabilities

Using third-party extensions is unavoidable when working with any development framework. So you need to make sure the framework you choose allows for easily integrating extensions. To test this, we decided to integrate the TypeScript and Select2 libraries on Knockout, Vue, and React projects. 

TypeScript is essentially a JavaScript wrapper. It supports strong typing that’s used by many developers, so support for this language is an important feature of the framework. Integrating TypeScript into any of the three frameworks is quite easy. In fact, they all have third-party header files with strict type definitions for TypeScript. In addition, React supports a special .tsx format that’s similar to .jsx.

Read also:
TypeScript vs JavaScript: What’s the Difference?

Select2 is a popular jQuery library that helps you use drop-down lists conveniently. We integrated this library into Vue, React, and Knockout as well. 

Select2 subscribes to standard DOM events and performs all necessary operations based on them. It was easy to integrate this library into Vue and React projects, as these frameworks work with virtual DOMs. Knockout.js, unlike React.js and Vue.js, works with the same events as Select2, so there’s a good chance of Knockout and Select2 overwriting each other's events, resulting in errors. To avoid this, a developer has to control this Knockout feature manually. 

This is a typical example of the integration capabilities of these frameworks: it’s easy to combine Vue and React with third-party libraries, but Knockout requires you to write additional code.

It’s easy to combine Vue and React with third-party libraries, but Knockout requires you to write additional code.

Comparing performance

We’ve already mentioned that Vue and React work with a virtual DOM to make changes in markup, while Knockout uses the real DOM. This significantly influences framework performance, as changing the whole markup requires more time than editing parts of it. In addition, working with models is slower in Knockout because it wraps each property in an observable, turning it into a function.

To discover the most performant framework, we tested common operations in Knockout.js vs Vue.js vs React.js. Let’s look at the results:

 

Knockout

Vue

React

Create rows

336.7 ms

180.5 ms

182.1 ms

Replace all rows

335.8 ms

157.3 ms

158.8 ms

Partial update of rows

70.4 ms

81.9 ms

156.4 ms

Select row

10.0 ms

10.3 ms

10.6 ms

Swap rows

108.6 ms

106.5 ms

20.0 ms

Remove row

52.9 ms

49.6 ms

54.2 ms

Create many rows

3081 ms

1935 ms

1603 ms

Append rows to a large table

3352 ms

268.6 ms

342.5 ms

Clear rows

366.7 ms

175.4 ms

191.9 ms

Table source — JS web frameworks benchmark on Stefan Krause’s blog

As you can see, Knockout significantly loses to Vue and React in terms of performance. In turn, the performance of Vue and React is almost identical. React is significantly better at swapping two rows in the table, but such operations aren’t always necessary.

Conclusion

When we compare Knockout.js, Vue.js, and React.js, we see that Knockout is the least favorable choice. It uses outdated features and produces complex and hard-to-read code. Integrating third-party libraries into Knockout or using modern technologies such as Redux is tricky. In addition, it loses to Vue and React in terms of performance. Still, Knockout is a lightweight framework equipped with basic web development features that performs well in small and simple projects.

Comparing React and Vue is far more complicated, as there are no obvious indicators of what JavaScript framework to choose. Both support a component approach, state system, and Redux architecture. React doesn’t support two-way data binding, whereas Vue does. On the other hand, the React community is larger and the technology itself is more mature, which means there are more answers, libraries, and ready-made solutions. When choosing between React and Vue, it’s best to focus not on the characteristics of your project but on your development team’s skills. 

At Apriorit, we’ve mastered many JavaScript frameworks including Knockout, Vue, and React. Contact us to discuss how our web development team can help you deliver your project!

 

Let's talk

4000 chars left
Attach a file
Browse
By clicking Send you give consent to processing your data

Book an Exploratory Call

Do not have any specific task for us in mind but our skills seem interesting? Get a quick Apriorit intro to better understand our team capabilities.

Book time slot

Contact Us

P: +1 202-780-9339
E: [email protected]

8 The Green, Suite #7106, Dover, DE 19901
United States

D-U-N-S number: 117063762

btnUp