React + Backbone: Keeping the LiveChat Tech Stack Fresh

Łukasz Wojciechowski in Product, Programming, on November 17, 2017, Comments

LiveChat Technology Stack

Nearly all developers wish they worked on a greenfield project, that is the one that contains a new, fresh and trendy technology stack. There is one problem with it: the tech world moves too damn fast! It’s just a matter of months, maybe a year, and your super sexy project is technologically obsolete again. Keeping your stuff clean, tidy and pleasant to work with is, and always will be, your job.

The old, the new and the busy

The problem of the aged technology stack is especially painful if a company continues to develop a piece software for a really long time. Some solutions which were fresh a couple of years ago are already outdated. Does it mean, though, that a product should be rebuilt from scratch on a regular basis? Not necessarily.

Let’s take the LiveChat Agent App, for example. It has been on the market for over a decade and we still live with the technical decisions that had been made back then.

LiveChat Agent AppLiveChat Agent App

Does it mean that the only options are rewriting the product completely or using just the legacy libraries? Of course not! We decided to go the third way and spice up the old technology.

Backbone meets React

The LiveChat agent app runs on the Backbone library. We chose it because of its flexibility and a subtle, light-weight structure that leaves us, the developers, a lot of space for fine-tuning. The time flew by, and this attribute still holds. Over the years, however, a plethora of new, modern solutions appeared and one of them plays really well with our old friend. Here comes the Backbone + React combo!

Why React, you may ask?

React is developed with a specific goal in mind: it aims to build, maintain and render HTML very fast. That makes it the perfect candidate for Backbone’s render engine. What we wanted to achieve was connecting Backbone’s events and models structure with a fresh and modern component rendering engine.

In our new projects, React is used to start a root component with ReactDOM.render() and then it goes down the road. But that’s not the only way. You can easily run the render function multiple times in various independent parts of a larger app, exactly where you want to.

Let’s have a look at a practical example taken from the LiveChat Agent App itself.

Old brain, young muscles

The Visitors section of the LiveChat Agent App is a very busy place. It displays all users that is currently on the website and allows to perform different actions on them.

LiveChat Agent AppLiveChat Agent App - the Visitors section

Depending on the website traffic, we can have lots of rendering job there. Obviously, we encountered performance issues when we used to simply re-render the whole DOM tree. We needed a solution that could compare the new and the old tree in a smart way and apply only the changes that we have made. And this is exactly what React is famous for.

We started small by simply extending the Backbone.View class and rewriting the render function so it could use React features. A very simplified version of our modifications looks like this:

function Visitor(props) {
  return <p>There is {props.name} on your page!</p>
}

const VisitorView = Backbone.View.extend({
  render() {
    const name = this.model.get('name')
    ReactDOM.render(<Visitor name={name} />, this.el)
  },
  remove() {
    ReactDOM.unmountComponentAtNode(this.el)
    Backbone.View.prototype.remove.call(this)
  },
})

What is vital here is the clean up in the remove function to let React unmount and detach properly.

That was quick and easy. However, there was another React feature that we wanted to use.

React comes with a rerender which makes all the diff matching magic happen behind the scenes, resulting in a lightspeed app refresh. It’s especially effective with all the new and shiny React fiber architecture. Now, how about keeping the Backbone model’s properties in sync with React’s state? Backbone models emit a lot of useful events over their lifetime. The one that’s handy here is change. We can attach setState() to it and call it just as we would do in a React app. And it all just works!

And they lived happily ever after

Having paired Backbone and React successfully, we can now slowly migrate our codebase to the new architecture, taking advantage of the fast renders. But the job is not done here: no project will maintain itself. Remember that it’s our responsibility to make our applications fun and easy to work with by keeping the technology stack up-to-date. The project’s age is not an excuse. At least not at LiveChat!