Migrating AngularJS to React without a rewrite freeze
The big-bang rewrite is the project that's always 80% done. Here's how to migrate a legacy AngularJS app to React while the product keeps shipping.
Every team carrying a large AngularJS app eventually faces the same temptation: stop the world, rewrite everything in React, ship the shiny new version in six months. That project is almost always still "80% done" eighteen months later. There's a better way.
Strangle, don't rewrite
The Strangler Fig pattern is the whole strategy: wrap the legacy app, route new and migrated features through React, and let the old code base shrink one route at a time. The product never stops shipping because at no point is the app broken.
A migration nobody can feel is a migration that survives the next quarterly roadmap review.
Make the two frameworks coexist
The mechanical core is mounting React components inside AngularJS and sharing state across the boundary. A thin adapter directive lets an Angular template render a React tree:
angular.module("app").directive("reactBridge", () => ({
restrict: "E",
scope: { component: "<", props: "<" },
link(scope, element) {
const render = () =>
ReactDOM.render(
React.createElement(scope.component, scope.props),
element[0]
);
scope.$watch("props", render, true);
scope.$on("$destroy", () => ReactDOM.unmountComponentAtNode(element[0]));
},
}));New features get built in React from day one. Existing screens migrate when they're touched anyway — a bug fix or a redesign becomes the moment to port that route.
The leadership half
The technical pattern is the easy part. The hard part is holding the line on three commitments:
- No freeze. The roadmap keeps moving; migration work rides alongside feature work, never instead of it.
- Migrate on touch. Don't schedule a "migration sprint" — convert screens as the product naturally revisits them.
- Delete loudly. Celebrate every AngularJS file removed. Shrinking the old surface is the actual measure of progress, not lines of React added.
Done this way, the migration finishes not with a dramatic cutover but with a quiet commit that deletes the last Angular module — and nobody outside the team ever noticed the ground move.