We Frankenstein’ed our monolithic project’s legacy code with React and maybe you should too

Photo by Chris Hall on Unsplash

If your company has preexisting knowledge of other libraries or frameworks such as Angular (current versions) or Vue, React is not the only viable choice but it was our choice.

After getting some time free from my daily tasks, I built two small prototypes of React/Redux modules and implemented them in our old code. The first was the base for a globally present info-center, an information hub the user can slide in from the sidebar to check error and notification messages. The other one was a mock that I placed in one of the many larger .jsp pages to check if both modules would work and could use the same Redux store without causing problems with the existing jQuery and AngularJS code.

[ cue evil laughter ]

Photo by freestocks on Unsplash

These are the steps we took to make this work and keep it scaleable

Separation

Being build as a Java/Spring Boot/Maven project, our code is divided into multiple Java modules containing the backend code as well as a “web-module” with our old frontend code.

Bridging two worlds

As our project is still mainly AngularJS code living in .jsp files and we needed to be able to initialise React components and modules in many different places in our old code, we had to build a bridge between both worlds.

// src/utils/reactBridge.js
import renderInfoCenter from '../components/modules/info-center'
import renderModuleA from '../components/modules/moduleA'
import renderModuleB from '../components/modules/moduleB'
const reactBridge = {
renderInfoCenter,
renderModuleA,
renderModuleB,
}

export default reactBridge
// services/reactBridge.js
angular.module('Services').factory('reactBridge', function () {
'use strict';
return window.reactBridge;
});
// angular-base-layout.jsp
<
script src="${BASE}/webjars/frontend/vendor.js"></script>
<script src="${BASE}/webjars/frontend/base.js"></script>
[...]<script>
window.reactBridge.renderInfoCenter()
</script>
import store from '../redux/store'
import { addNotifications } from '../redux/actions/notifications.actions'
import { dispatchActionForModuleA } from '../redux/actions/moduleA.actions'

const bridgeDispatch = (func, payload) => store.dispatch(func(payload))

const reduxBridge = {
addNotifications: payload => bridgeDispatch(
addNotifications,
payload
),

dispatchActionForModuleA: () => bridgeDispatch(
dispatchActionForModuleA,
payload
),

onStateChanged: (callback) => {
store.subscribe(() => {
const state = store.getState()
callback(state)
})
}
,
}

export default reduxBridge
// services/reduxBridge.js
angular.module('Services').factory('reduxBridge', function () {
'use strict';
return window.reduxBridge;
});
// somewhere in our code...
showInfo : function(message) {
var data = getMessageData(message, 'info');
typeof reduxBridge === 'object'
? reduxBridge.addNotifications([data])
: console.log("reduxBridge not available after timeout")
},

Decide for each Feature Request individually

If I had all the time in the world, I would completely rewrite the old project, bit by bit for every request that the customer makes. In an ideal world, that might be possible. In reality, though, you have to make some tough calls and keep your customer in mind, not only your developers. Finding a healthy balance is key here.

What did we gain?

With all the changes we made and our new React/Redux frontend-module, we’ve made a lot of improvements both for us and the customer. Here’s a short and not exhaustive list:

  • Webpack Dev Server for better FE code development
  • modular and reusable react components
  • more velocity with every completed feature
  • new code is easier to test and reason about
  • mock data / API for development independently from BE team
  • Redux store as a single point of truth instead of old AngularJS scope
  • Redux middleware as an abstraction layer between frontend code and API
  • no need for a complete relaunch
  • reduction of technical debt
  • we can pick an attack the most relevant parts of the code when and where we want
  • even more motivated team members than before

What did we lose?

We spent some time on our internal budget to develop a prototype before addressing the customer and starting to solve feature requests with the new setup.

Some words about me:

If you want to read more of my articles, feel free to check out my author page or my series on building a React Native Web App with Hooks, Bells, and Whistles with Expo SDK33. I’m also currently working on a new series about building more complex and scalable apps using React/Redux, where I’ll go into details about how and why I do stuff the way I do as well as some articles on my experience in building games for web and mobile with React.

I’m a Web / App Developer & father 👨‍👩‍👧 doing freelance and part-time agency work since 2003, 💻 building stuff on the side 🕹 and attending conferences 🎟

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store