First major migration

The first task that needed to be done was to migrate the Extranet code from the Django codebase into it’s own repo and deployment setup. This entire journey has been captured in my previous blog post.

Just to summarise, I am listing down the benefits that we achieved post this migration.

The obvious benefits of breaking down the monolith. Can now work on Extranet standalone and ship faster

One command to build them all — previously it was a mess with developer having to run a separate script for legacy and react code and commit the built files. With the help of some custom bash scripts we were able to consolidate everything into one single build command.

— previously it was a mess with developer having to run a separate script for legacy and react code and commit the built files. With the help of some custom bash scripts we were able to consolidate everything into one single build command. Benefits of Create React App — Babel, ESLint, HMR (yes, this was missing) and added Prettier on top of that too.

— Babel, ESLint, HMR (yes, this was missing) and added Prettier on top of that too. Benefits to the user — Optimized build process resulted in some size savings as well without making any change. PWA (although not fully utilizable since we still have legacy code shipping separately).

Another major Gotcha I’d like to call out here is that, even though our webapp is a Single Page App, we figured out a way to maintain hierarchy of HTML files that eventually gets combined to one. The how is mentioned in the above post.

Strategies to introduce React into legacy code

Simple Mount

Let’s start with the most easiest and commonly used way. In this, we create a container element in the HTML, and from our JS code we can do ReactDOM.render onto that element.

Simple React code mount in a part of legacy code

Conditional Mount

Now as you progress during your migration, you will end up in places where the screen you are trying to revamp will show up conditionally, including the mount point you have. In this case, you can make use of Event dispatches to render the React code. This pattern is pretty powerful to make changes in some part of the screen.

Conditional React code run in a small part of screen (legacy code)

React in the driver seat

So now, with the mix of above strategies, we were able to migrate close to half of our application. But now we were missing a few things which is crucial to the development, as well as sanity of the whole code base as such.

We needed Global State (ex: Redux) to share data between React screens

(ex: Redux) to share data between React screens We needed to add a new Route with nested routing , which wasn’t possible with the simple routing logic we had.

, which wasn’t possible with the simple routing logic we had. We needed to introduce deep-linking to existing sub tabs we had.

With the above requirements in mind, we decided to introduce React as the entry point of the application, and force legacy code run in some of the tabs instead of the other way around (current situation). With this, we can introduce React Router, and global state (via React.Context) at the top level.

Let’s look at how our web app runs

Old code flow vs New code flow

The all too familiar src/index.js which now runs post legacy initialized itself

We need to talk about Hooks

During this migration we also have started to adopt React Hooks. And so far the experience of writing with hooks has been amazing🔥. Listing down things that we found beneficial.

We are now writing far lesser code compared to before

Our code looks more readable now with“effects” which majorly for us is to run our legacy code in certain places. They are invoked properly and cleanup after themselves too. This enabled us to not migrate legacy code but make it work within some of the routes in React.

The magic code which is making it possible to run legacy code in certain screens

The code is more readable to someone who is new to React since they don’t have to understand the intricacies of this

And we still haven’t gotten around to extracting commonly used code into custom hooks. 😶

Impact

Over the course of all these changes, I would like to call out the impact that we have delivered to the user. After all our commitment is to deliver the best user experience to our customers!!