Anybody who's been working in front-end more than a month is aware of the breadth of frameworks and libraries out there. Like aspiring athletes, they compete for a chance to be in the spotlight and hold the title, for a fleeting moment, of the most popular platform.
In that ever changing landscape, many of us find ourselves wishing we could try the new tech that all the cool kids are talking about. But our customers aren't interested in whether we're using Ember, Backbone or Vue, they just want a working product and the new features they’ve been waiting for. And so we do what makes sense: we pick a tech and stick to it. This is the situation we're in at Flexera. We have a collection of front-end applications built with: React, Angular 2 and AngularJS 1 to only name the most recent tech.
The need for change
We started the year by adding one more tech stack when we defined a new standard for our green field apps. We decided to go with React, TypeScript and styled-components and started building a new components library to implement our designs and patterns in a reusable manner.
Integration is also a strategic focus this year, as we have many powerful capabilities siloed into separate products. There's an ambitious and exciting plan underway to support this on our back-end. At the UI level, this translate to merging our various products into a single interface where our users will find everything they need in one place.
This is not a simple task as we have years of work in our various apps and some of our UIs are fairly complex. So we thought through the various ways we could tackle this: from full rewrite to simply updating our CSS styles.
In the end, we decided a good compromise would be to merge our older single page applications into a brand new, single front-end. We would start by embedding the existing code, framework and all, in the new project. Then over time old code would be converted or replaced while new features would be built straight with React.
Anything using a server-side framework such as Ruby on Rails or ASP.NET MVC is too different to be handled in the same way and would need to be rewritten or kept separate.
Testing the water
The first step was to confirm the idea was technically feasible.
We put together a test React application based on our new standard. Then we defined a small set of experiments to determine if an app built on another framework could be embedded in our test app:
- Can we render the embedded app?
- Can we use react-router in our React app and render the embedded app on one of the pages?
- Can we route from a sub-page of the embedded app to a sub-page of the React app?
- Can we route from a sub-page of the React app to a sub-page of the embedded app?
- Can we refresh the browser while on an embedded app sub-page and remain in the right context?
While we focused on AngularJS 1.5 and Angular 2; these checks will apply to any other framework as well.
Of course the first thing a developer should do when faced with a new problem is search online to see if someone else has already solved it. Surprisingly, most results explain how to render React components within Angular applications and not the other way around, it's clearly a more popular approach but it wouldn't work for us.
Thankfully, a couple of posts stood out:
- For AngularJS: https://medium.com/appifycanada/angular-components-in-react-2c929130f995
- For Angular 2: https://dzone.com/articles/using-angular-2-components
Those were both useful starting points and got us on our way. With some additional tinkering, we were able to check all the boxes and proceeded with our plan.
So we're starting from a set of standalone applications, with different framework, build tooling and deployment strategy. And our end goal is a single React application with chunks of Angular 1 and 2. Oh and by the way, they all need to look like they fit together.
It's a big task and we can't really stop all feature work until all of our applications are unified. So we've decided on a staged approach where we take one or two apps at a time through a migration path:
Common build tooling
In order to merge multiple apps into one, we need to be able to bundle the code together. Our new UI standard uses a fairly straightforward Webpack configuration and so our first step when migrating an app is to update its build tooling.
It can be a tedious process especially when an app was not using ES6 modules, in that case we need to go and update every single file. But in it end it's well worth it: a good and coherent build set up will make our life easier in the long term.
Next, we add React to the mix by wrapping the old app in what we've been calling a React shell. The idea is to replace the app's top bar and navigation with new React components from our common components library.
This step leverages what we've learned during experimentation and goes a bit further. Along the way, we ran into some interesting challenges:
- Implement permission checking in React to show/hide navigation items
- Routing edge cases
- Global CSS issues affecting the new components.
And in the end, we had an interesting patchwork of an app: with two different styles glued together.
And so the next logical step is to update the styling of what remains of the legacy code. It's not particularly exciting to dig through archeological layers of old CSS. Yet it's a necessary step as our goal is to ensure a great experience for our users; and a UI sporting 4 or 5 different style sheets does not exactly inspire confidence.
We opted to first release our refreshed apps as is, it allows us to merge all of our changes back and catch any glitch before taking on the next steps.
It also makes the transition less abrupt for our users: first get acquainted to the new designs, then later things may be shuffled around a bit.
Merge to unified UI
In parallel we've prepared our new unified UI. It's a brand new project which will progressively host all of our UI functionality. In order to account for an ever growing single application, we decided to rely on Webpack's dynamic import support to lazy load only the relevant chunks.
Our freshly migrated new app will be merged into the unified repository and integrated into the main navigation. By then, everything will be quite straightforward.
Where are we on this journey?
As we're entering into September, we have two Angular (1.5 and 2) applications in the process of being migrated. Plus one green field app which is waiting for the unified UI app to be ready. By the end of the year, all three will be merged together and we'll start working on the next batch. Any new UI functionality will be directly added to our one UI.
While we're far from done, we've mapped our path and are confident we'll reach our destination successfully. I fully expect to run into unforeseen obstacles and that we'll get past them. It's an exciting journey and I look forward to posting about it again in a few months and share what we learned along the way.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.