7 Tips for migration from Backbone to React & Redux
How to stop worrying and start using modern frontend technologies
If your web-application was initially written with Backbone, you probably may want to migrate it to more modern React framework these days. React has many advantages compared to Backbone and the reasons of such decision could be obvious. However, it’s not the topic of this article. Let’s just suggest that you’ve already decided to make this step. What are you going to do?
Developing a new application with React from the scratch could be not really the best way to deal with it. This process requires maintaining of two applications together at the same time, which is going to take much more resources from you than if you have just one of them as before.
Therefore it would be much easier to combine Backbone and React together in a single app for sometime — create new features with React, upgrade the existed ones with Backbone and migrate gradually, step by step.
Developing a new application with React from the scratch could be not really the best way to deal with it. It would be much easier to combine Backbone and React together in a single app for sometime.
At least, I did it this way during such migration of our application and I wasn’t disappointed. Here’s the list of approaches and tips that I applied. I believe that reading of this would help you to proceed the same and finally get new technologies in your project!
1. Embed React components
When you use Backbone, you organize the interface of your app with Views. Such view contains an HTML-template that you need to render in a DOM-node, and usually you have to manually call the render method to do that.
React provides Components for the same purpose. A component’s render method returns JSX-template instead of HTML.
When you migrate to React, you have to mix this approaches up somehow. There are two ways to do that.
First of all, you can embed React components in your Backbone views. This means that a view will render not an HTML-template or sub-views (like it usually goes), but React component as a sub-view.
For example, let’s look at a standart implementation of the render method in a view with several sub-views. Here every sub-view renders into an individual DOM-node:
And then let’s look, how we can start using React here:
We just replaced one of subviews with a React component. That’s it! You can say that you started to rewrite you app with React now. You have this component and when you work with it, you can absolutely forget that you use it inside of a Backbone app. It doesn’t matter, how big is this component — it could include just pair of text nodes or a big hierarhy of children components.
You have this point of the entry for React now, but it doesn’t mean that you should have just single one of them. You can embed another React component in another Backbone View the same way. And you can do it as many times as you need.
Of course, you will not get all the advantages of React virtual DOM with this approach because of several different hierarchy. But after some time, when you have more components in your project, you will be able to remove the Backbone interlayer from the between of this components and connect them together. Actually, this is the plan how to grow your lonely React components to the whole application written with React.
It could be something like this when we decide to rewrite the header with React:
Then we can replace the content too, and we will no longer need the entire Backbone page view here (Header, Content and Footer is in the page component now):
This approach is very useful if you have a big Backbone application with several pages and its own routing, because you can start use it anytime and anywhere inside of the app. Although if your app haven’t grown up yet, welcome to the next section.
2. Wrap the app up with a React component
If your Backbone app is small and includes just one page, but you plan to extend it with other ones and use routing obviously, the migration to React is probably even easier in this case.
You can create an ordinary React app architecture using react-router to route between pages, write new pages as React components and wrap the single Backbone page that you already have with a component too.
Let’s pretend that we already have the dashboard Backbone page view, but decided to write new pages for autentification with React. Here is how our Router could look like:
We will make Login and Signup pages as components, but what about Dashboard? Here you still have to create the Dashboard page component. However, it will actually render an empty DOM-node and then the Backbone view will be rendered into this node through the componentDidMount life-cycle method.
After some time you can rewrite your dashboard with React and then get rid of Backbone at all. You can also mix this approach up with the first one and start creating some components inside of Dashboard if it’s too hard to rewrite the whole view at the moment.
3. Adapt existed data for Redux
If you use React, you likely want to use it in a bunch with Redux to get all the advantages. Okay, it could be not Redux, but something another — Flux, MobX, etc. The idea is similar anyway.
Backbone views work with data in a Backbone way — using Models and Collections. Usually a view keeps Models/Collections instances with the needed data inside. These instances could fetch data from the server and provide some useful methods to work with this data.
Other words, when you embed a React component, it could require data that already existed in Backbone. To not fetch it twice with Redux, you can just put data from Backbone in the Redux Store before component mount and then work with it in the familiar Redux way.
Of course, if you want to connect React with Redux using react-redux, you need to wrap your every point of the entry up with the Provider component to make this library work (unlike an usual React app where you have just a single Provider on the top of the hierarchy).
There are two ways to put existed data to the Redux store. If you create a store after the data fetched, you can use the initial state for it:
Another way to do that is to dispatch actions that will put data in the already existed store:
Notice also that we started to use the Provider component as were said above.
4. Synchronise data between Redux & Backbone
When you put the data from Backbone into the Redux store, you will be able to use it in React components in the Redux way. But the data could be changed by actions of a user in Backbone views. It will be changed in a model or a collection, but stay outdated in the store. To prevent this problem you need to synchronise the data between these two frameworks.
Use dispatching of the corresponding actions for that. For example, if you change the title in one of the tasks’ models, dispatch the action doing the same in the store:
You can also do the backward synchronization for a case when data be changed inside of a React component. Here you need to use the subscribe method of the Redux store to listen when it changes:
5. Use the Webpack power to divide the stacks
When you bring React on the board, you have to use a special Wepback-loader to handle JSX-syntax in your code. If you want a faster building process, you’d better put all your components in an individual directory (let’s suggest that you named it “react”) and take JSX-loader only for it, not for the whole project (using JSX-loader everywhere will work too because it is compatible with the standart JS-syntax, but it will work a bit slower).
Also, you might want to use not just CSS in your components, but much more advanced CSS-modules. And Webpack can help in this situation too. All you need is the right config — you can still use CSS-loader you used before in the Backbone part of the project, but other options for the same loader to turn the CSS-modules on in the React parts of it.
That’s how such Webpack config could look like:
6. Stay away from the previous stack
Try not to use the architectural solutions from the Backbone part in the growing React part if they don’t suit there. They may be applicable and you may have temptation to embrace them instead of taking time on implementation of much more appropriate ones, but remember, your main goal is to rewrite all the app with much more effective React. So, sooner or later you will go away from Backbone, and if its parts intersperse new architecture somewhere, it will be much more painful to get rid of the old one.
So, try to write the React part as if you don’t know anything about the Backbone part.
Try to write the React part as if you don’t know anything about the Backbone part.
The following situation could be an example here. You could have an instance of the main application view in the global namespace. This instance could keep some models inside and provide some global methods (for example, methods for verification of roles of the current user based on the model of this user) using everywhere in the Backbone part of the project. It could be a normal approach for Backbone, but we use the Redux store for such things in the React & Redux bunch.
Here is how it could look like in a Backbone view:
Then, how it could look like if you use this (inappropriate!) Backbone way in a React component:
And finally, a right Redux way solution:
As you can see, it is difficult to stop using Backbone if your React components still have parts of it inside; and it requires nothing if you create components in the right way.
7. Start the migration in the right time
It could be not so reasonable to start replacing the Backbone views with absolutely the same React components (I mean design and functionality). Almost every web-application changes very often during its life-period — the old features give a way to the completely different new ones or simply acquire new UI or UX design. The whole pages disappear and the new ones come to their place.
In such conditions it would be wiser to apply React only to appearing new features that gradually will replace the old ones. You will need to make those new features and it will take your time anyway. So, it’s a good opportunity to spend this time using the new stack, not the old one. And it must be even faster, effective and pleasantly to make new parts with React (after all, it’s the reason why we choose React, isn’t it?).
It would be wiser to apply React only to appearing new features that gradually will replace the old ones.
Of course, if you have much free time to simply rewrite a Backbone application as it is, it could be an option too. But it’s a rare case and it’s hardly possible in the real life.
P.S. Be patient
It could take a long time until the whole application be migrate to React. Be patient and don’t feel remorse about that. The best part is that you are already on this way. You make all the new features with React, use its advantages, don’t waste time to migration itself only and still make valuable things for the business. Let everything go in this way and sometime you will get the migration done. ⚛️