Cutover

React migration

Goal

Goal

To migrate the AngularJS app to React.

Problems to solve

#Support
AngularJS was coming to the end of life in terms of support from the maintainers.
#Test coverage
Due to the speed-to-market delivery of the initial app, there were deficiencies in the testing coverage.
#Hiring
To ensure the company has access to the best talent available we need to be using a modern front-end architecture.

Solutions

Microservices
AngularJS ShellSingle SPAReact Micro AppShared State
We were able to embed micro react apps inside of the main structure of the Angular JS app. This was achieved using Single SPA. We began by migrating low traffic areas of the site. The React app itself went through several iterations of approaches but eventually settled on a similar approach to the existing AngularJS approach.
Code flags
Build FeatureFF Active?Serve React VersionServe AngularJS VersionRemove Flag
We introduced switches that allowed us to define which parts of the site could be switched between AngularJS and React. These also mitigated risk on rollout as we had the ability to switch back to legacy implementations if we needed to. The flags were managed via a management page. We introduced best practices ensuring these flags were removed after full adoption.
Clean JS architecture
AngularJSReactFuture JS LibraryView StateState ManagementVanilla JS Core
The team proposed applying Robert Martin's Clean Architecture principles — well established in back-end systems — to the front end. The innermost ring would be a pure Vanilla JS core: business logic written to the SOLID principles with comprehensive unit test coverage and zero framework dependencies. Surrounding it, a state management layer (MobX) and view state adapter translated core logic into what the UI needed. The UI frameworks — AngularJS today, React or any future library tomorrow — would sit in the outermost ring as entirely swappable adapters. New JS trends could be adopted by writing a new adapter without touching the core. The approach was theoretically sound but proved unpopular with engineers due to the overhead it introduced and was eventually set aside in favour of co-located React Testing Library tests and Cypress E2E coverage.

Take aways

  • These things take much longer than anticipated. There was a lot of wavering on the best approach. Ultimately I think a 3rd party opinionated approach via an established framework would have wielded quicker results.
Target