GSD

Migrating from AngularJS to React

Posted by Paige Niedringhaus on October 2, 2023

It won’t necessarily be an easy task to undertake, but in the world of software doing nothing and expecting things to continue to “just work” is worse.

Back in 2018, my software development team was faced with a tough decision. It was announced that the framework we’d been using for over 2 years to build our application of record, AngularJS, was entering long-term support (LTS). This meant that new features, security patches, and further support from Google teams regarding framework issues would essentially cease.

After evaluating our options including upgrading from AngularJS to Angular (the name for every version of Angular 2 and beyond) or migrating and rewriting our application in a completely new JavaScript framework: React. We ultimately chose to go with ReactJS.

In the following article, I’ll walk you through how to migrate an AngularJS application to React, as well as some of the considerations you’ll need to keep in mind planning your own migration strategy.

Why migrate to React from Angular?

As I said, we evaluated a few different, popular JavaScript framework options but ultimately ended up settling on React, and here’s some of the main reasons we did.

  • Speed - Application performance depends on a variety of factors including the user’s Internet connection and the amount of data being rendered in a view, but because React relies on a “virtual DOM”, which allows developers to make changes without having to rewrite the full HTML document, and starts off as a smaller bundle size than AngularJS, it generally ensures speedier performance by rendering updates faster.
  • Weight - React has a smaller bundle size overall than AngularJS - even with React DOM and Redux libraries included. If you look at this comparison chart, you’ll notice that React started out smaller than AngularJS, and as it’s progressed to newer versions, it only continues to get more compact.
  • MVC - While this reason for migrating is debatable, React is a UI-focused library, which provides more flexibility and freedom of choice about which additional libraries to use and how to organize an application’s code, whereas AngularJS is a full-featured MVC framework with strong opinions on how applications should be built. Depending on your team’s style of development and your app’s needs, organizing your code as it makes sense to you, may or may not be a welcome option.
  • JSX syntax - Unlike AngularJS, which relies heavily upon HTML injected with Angular-specific syntax to enable things like two way data binding and connecting JavaScript controllers to UI views, React took a different (arguably more straightforward) tact. JSX, an extension of JavaScript, produces React elements to describe what the UI should look like with the full power of JavaScript at its disposal. Functions, if statements and for loops, and JS expressions are all available in JSX syntax. And instead of artificially separating technologies by putting markup and logic in separate files, React separates concerns with loosely coupled units called “components” that contain both. This makes components more readable, reusable, modularized, and easier to extend with additional logic as needed, as all the logic is already in one place.
  • Unidirectional data flows - One of the originally touted benefits of AngularJS was its two way data binding, which served to synchronize the model and view without having to click a button or refresh an entire page. While this was good in theory (and smaller applications), in practice it became cumbersome and made the UI slow, especially when there were lots of pieces of dynamic data on a page - think tables with lots of rows of data, for one. On the flip side, React has always subscribed to a unidirectional data flow, meaning data flows only one way: down, in the application. Parent components pass state and data as props to child components, and since the data can only flow one way the code is less error prone, it’s easier to debug, and it’s more efficient for the library to handle.
  • Simpler code - React code syntax is closer to vanilla JavaScript making the learning curve (and code) simpler: if you know JS, you can probably pick up on the basics of React pretty quickly. AngularJS has a lot of its own special syntax to accomplish the same things, but understanding how the code works for those unfamiliar with it can be more challenging.

Let me give you a code sample to illustrate my point. 

Below are two snippets of code used on the main landing page of the app to display cards with links to various pages and functionality The first code snippet is written in AngularJS’s HTML syntax.

AngularJS code:

    <md-toolbar class="transparent-toolbar">
    	<div class="md-toolbar-tools">
    		<div class="md-display-4" id="page-header">
    			Dashboard
    		</div>
    		<span flex></span>
    	</div>
    </md-toolbar>
    <div layout="row" layout-sm="column" class="button-row">
    	<div flex="33" layout-padding class="layout-padding flex-33">
    		<md-card class="clickableOptionCard" id="manageCard" layout-align="center center" ui-sref="manage">
    			<p class="fa fa-briefcase"></p>
    			<md-toolbar class="layout-align-center-center">Add/Drop</md-toolbar>
    		</md-card>
    	</div>
    	<div flex="33" layout-padding class="layout-padding flex-33">
    		<md-card class="clickableOptionCard" id="keyCard" layout-align="center center" ui-sref="keyManage">
    			<div ng-include="'dashboard/template/key.template.svg'" class="key-wrapper"></div>
    			<md-toolbar class="layout-align-center-center">Key Management</md-toolbar>
    		</md-card>
    	</div>
    	<div flex="33" layout-padding class="layout-padding flex-33">
    		<md-card class="clickableOptionCard" id="executeCard" layout-align="center center"
    		         onClick="window.open('execution/AMT2','_blank')">
    			<p class="fa fa-cube"></p>
    			<md-toolbar class="layout-align-center-center">Execution</md-toolbar>
    		</md-card>
    	</div>
    </div>
    <div layout="row" layout-sm="column" class="button-row">
    	<div flex="33" layout-padding class="layout-padding flex-33">
    		<md-card class="clickableOptionCard" id="triangulationCard" layout-align="center center" ui-sref="triangulation">
                <div ng-include="'dashboard/template/triangulation-icon.svg'" class="triangle-wrapper"></div>
    			<md-toolbar class="layout-align-center-center">Triangulation Report</md-toolbar>
    		</md-card>
    	</div>
    </div>

    The second code snippet is the same functionality written in React’s JSX syntax. Tell me in the comments which code looks cleaner and easier to read to you.

    ReactJS Code

    import React, { Component } from 'react';
    import { NavLink } from 'react-router-dom';
    import KeysImage from 'assets/images/key.svg';
    import StatusImage from 'assets/images/pro-direct-circle-outline.svg';
    import ReportsImage from 'assets/images/health-check.svg';
    import AMT2Image from 'assets/images/truck.svg';
    import Card from 'commonComponents/Card/Card';
    import './Dashboard.scss';
    
    class Dashboard extends Component {
        render() {
            return (
                <div className='headerBorder'>
                    <hr />
                    <div className='dashboard'>
                        <Card>
                            <a href='/keys'>
                                <span className='image-wrapper'>
                                    <img src={KeysImage} />
                                </span>
                                <h2>Key Management</h2>
                            </a>
                        </Card>
    
                        <Card>
                            <a href='/manage/'>
                                <span className='image-wrapper'>
                                    <i className='icon_scan' />
                                </span>
                                <h2>Add/Drop</h2>
                            </a>
                        </Card>
    
                        <Card>
                            <NavLink to='/status/change' onClick={this.resetChangeStatusPageFlag}>
                                <span className='image-wrapper'>
                                    <img src={StatusImage} />
                                </span>
                                <h2>Store Status</h2>
                            </NavLink>
                        </Card>
    
                        <Card>
                            <a href='/triangulation'>
                                <span className='image-wrapper'>
                                    <img src={ReportsImage} />
                                </span>
                                <h2>Triangulation Report</h2>
                            </a>
                        </Card>
    
                        <Card>
                            <a href={this.state.AMT2Url} target='_blank'>
                                <span className='image-wrapper'>
                                    <img src={AMT2Image} />
                                </span>
                                <h2>AMT 2.0</h2>
                            </a>
                        </Card>
                    </div>
                </div>
            );
        }
    }
    };
    }
    
    export default Dashboard;

    Ultimately the decision to migrate from AngularJS to React was agreed upon because it would benefit both the users and the development team. A win-win situation. 

    Migration options

    There are a number of options when it comes to application migrations based on how your existing application is built. Let’s go through some of the approaches out there now.

    • Rewriting your application completely - The most extreme option, but sometimes the only one. In this scenario, all work on the current AngularJS application is halted and the app is rebuilt from the ground up in React. Unpopular amongst product managers and customers because new features cease while the app’s functionality is recreated in the new framework, if the existing app is slow and difficult to debug and maintain, it may be the right option.
    • Create a separate application and migrate one part at a time - This approach involves having two separate UI applications running, and depending on where the user is in the application, they’ll either be in the AngularJS version or the React version. Routing back and forth between the two apps, while still feeling like a single application in terms of user experience can be tricky, but it allows the development team to continue to deliver new features in the new framework, and move over existing functionality from the old application one piece at a time until nothing remains. Once all functionality is recreated, the legacy app is shut down completely.
    • Micro apps - A relatively newer architectural pattern that involves breaking up a single UI repo into several smaller web apps that work together to form the whole. They could be divided up by: feature, page, or domain, to name a few. This makes each piece of the application smaller, more modular, and easier to maintain and develop, while also making it simpler for more development teams to join in and build new functionality as required. This approach, while it requires greater cross-team communication, has the added benefit of letting teams choose the JS framework they like best without impacting the other teams’ choices
    • Using a library to translate Angular components into React* - There are libraries that emerged when the retirement of AngularJS was announced without a clear upgrade option to Angular or React, which involved installing the library, and it could handle transforming existing components so React could render it.
    • Single SPA* - another approach adopted by some teams was to add React to the existing AngularJS repo and have the two work together in a single application. This sort of situation could arise because there are not enough resources or time to rewrite the existing application - feature delivery must continue, or when two separate apps built with different frameworks end up needing to become one.

    * While the last 2 options listed are approaches that some development teams chose, I do not recommend them. Relying on third-party community-built libraries or getting different JavaScript frameworks with very different approaches to how applications should be designed and architected to work together as one makes for unsustainable code: debugging applications will be more difficult and finding developers proficient in both frameworks will be more difficult as well. If at all possible, avoid these options for more clear-cut ones.

    Benefits of migrating from AngularJS to React

    I covered some of the benefits gained by migrating from AngularJS to React earlier in this article, but there’s more you might not recognize right off the bat. Here are a few more to help convince you.

    • Version migration is easy in React - Especially after no clear upgrade path was provided from AngularJS to Angular, backwards compatibility and ease of upgrades between different versions of React is a big selling point. From the get-go, the React team has worked hard to ensure that even as the framework continued to evolve, the earlier versions of the library still continue to work as well (heck, Facebook’s even provided codemods to automate code updates to existing React projects).
    • React skills work for React Native development - Although React Native is a separate framework designed specifically for building mobile applications, many of the skills a developer gains working with the React framework are applicable here as well.
    • React’s server-side rendering (SSR) is good for SEO - Unlike AngularJS, which is a client-side rendered application through and through, React (and many of the frameworks based off of it like Next.js and Gatsby) allows for server-side rendering, which is great for websites that rely upon SEO to drive traffic.
    • React keeps advancing - Generally, developers enjoy learning new things and building solutions to problems - that’s why many of us got into this industry in the first place! The fact that React keeps improving means developers will want to stay in touch with its new features and try them out in the apps they’re building. Framework evolution that improves the developer experience is good for the community and good for the long-term sustainability of this library.
    • More developers today know React - This benefit goes hand-in-hand with the last: because React keeps advancing (and is the most popular frontend framework right now), there are lots of developers who know it. When teams are looking to scale up, it will be easier to find new devs familiar with React (and hopefully some of the newest features it has to offer) as opposed to finding devs who know a more outdated framework like AngularJS.

    I have no doubt there are more benefits that come from migrating away from AngularJS and to React than I’ve listed here, but these are the ones that immediately came to my mind.

    banner-cta-react-blue.webp

    Challenges of migrating from AngularJS to React

    All of the above is not to say that migrating to React is pure sunshine and roses, there are challenges when taking this on. Here are some of the challenges you may run into along the way.

    • All helper libraries must be chosen - Unlike AngularJS which comes pre-installed with libraries for routing, data fetching, state management, dependency injection, and more, the core React library is very bare bones. Everything I just mentioned must be chosen and installed into a React app by the development team - and there’s always multiple, competing libraries to evaluate and choose from. 
    • Logic in AngularJS will need to be migrated into separate microservices - One of the tougher things about AngularJS was the fact that all sorts of complicated business logic lived directly in the client. This made recreating and debugging issues extremely tricky because everyone’s browser is different. One thing to take into consideration is how to extract that logic from the Angular app and put it somewhere that the React app can display it. (Personally, I’d recommend separate microservices that handle the logic and transformations and send the fully formed data back to the client app to display.)
    • React keeps advancing - This is a positive and negative. Keeping up with advances in technology (as exciting as it is) can be completely exhausting too. The introduction of React Hooks turned everyone’s understanding of functional components and state management on its head, and while it significantly pushed what can be done in React apps forward, it did take getting used to. Sometimes, stability is appreciated.

    Things to consider before migrating from AngularJS to ReactJS

    With all this talk of migration options, benefits, and challenges, you may think that’s all there is to this task, but there are a few more things I’d recommend you think about before committing.

    • Resources - Do you actually have the time, the people, the money, and the buy-in to undertake this process? Depending on the resources available, this migration may or may not be feasible.
    • Necessity - How critical is it that this migration happen? Are the users being negatively impacted by the current application? Does it require new features that are more cumbersome and time consuming to add than they should be due to the existing code base, or is the major development done and this app just needs to keep running as it is with minor bug fixes and support?
    • Have a plan - Too often development teams jump right into the coding portion of a project without taking enough time to develop a plan for an app to scale and grow over time. Before coding the new application, make an architectural plan of how to approach building this for maximum flexibility, life span, or whatever is most important to the team - this includes figuring out which pieces of the app will be migrated first, if business logic in the UI needs to be rewritten in new microservices, and if the new app will be available to all users from day one or just a subset as kinks are worked out.

    I don’t mean to discourage anyone from doing a migration if it’s the best thing, but take the time to evaluate the options and tradeoffs - this will most likely be a longer term commitment for the team.

    How to migrate from AngularJS to React

    Ok, so it’s been agreed a migration from AngularJS to React is in the cards. Now, how to actually go about it?

    Here’s a plan you can follow that my team used with success.

    Outline the pros and cons

    Migration of JavaScript frameworks is almost always not only up to the development team: product managers, designers, and upper management will also need to be on board with the plan. To assuage their fears, make lists of the pros and cons with a special focus on how it will benefit the users to show them it’s a beneficial and necessary step.

    Assess the opportunities and risks 

    In addition to the pros and cons, take this chance to identify places where the application could be improved in its next iteration, as well as plan for potential pitfalls. This could be things like: removing features not used in the current app, redesigning experiences in collaboration with designers to follow best practices, and how to effectively remove the logic from the current app into its own service so the new app could display the correct data.

    Diagram the new architecture

    Depending on what style of architecture your application is following, diagram what the new application will look like so everyone’s clear.

    For my team, it involved 3 new microservices to handle the logic and data transformation previously left up to the AngularJS application, 2 new databases, and 2 UIs that would work in tandem until the React app had all the functionality of the Angular app. Even if this architecture ends up evolving over the course of the migration, having a plan of how this could go from the beginning will be helpful as the migration progresses.

    Build a proof-of-concept

    Build a very pared-down version of the application to show it can be done - there’s no better form of proof than a small, working example app. If the POC needs to be able to route back to the first, make sure this works, and if automated testing is part of your team’s development workflow, write a few tests with the new testing frameworks to serve as an example for the larger migration. This too should help give the dev team and business partners confidence this will work.

    For our own POC, I built a very pared-down version of our app’s navbar and dashboard page, complete with links allowing it to successfully route back and forth between the React app and our existing AngularJS app. 

    Additionally, I wrote Jest and Enzyme unit tests to demonstrate how to go about unit testing the components, as test driven development (TDD) is another methodology my organization subscribes to. Jest is a unit testing framework that actually shipped with React if you use the Create React App CLI to make a new React project. And at the time, Enzyme was created by Airbnb and added additional functionality to Jest for even more robust testing. Before React Hooks (at the time we began the migration), this was the defacto unit testing combination. Later on, we used Jest and React Testing Library when Hooks were introduced to the project. Finally, I used Cypress.io for the end-to-end tests, as it was quick and easy to set up.

    Decide which parts of your application you will migrate first

    Unless the current app does everything in one single page, there are probably some pages or screens and functionality that will be easier to migrate to the new app than others. Think about pages that have more static components or where the display depends on data from backing services - these will be easier to tackle first. For parts of the AngularJS app that handle business logic, this logic will need to be extracted and rewritten into a separate microservice for the React app to consume and display. This will be one of the parts to migrate later in the process. Be sure to consult with the product managers as you make these decisions to take into account business needs and the product roadmap.

    My own team, when we began our migration, determined our login page, dashboard, admin pages, and user profile pages would be the easiest to migrate, as they were the least reliant on business logic. 

    These pages would not only give our developers a chance to start getting familiar with how React worked, in less complex, data-driven scenarios, but could also be done in parallel with the developers building the new microservices to house the old UI’s logic.

    The majority of the screens that were dependent on the business logic that had to be refactored out, were also identified, and the thinking was: the logic extraction would be done on the backend before those screens were greenlighted for migration to React. 

    Screens that were tied to logic included our checkout cart and all of the screens concerned with our users’ product assortments. For instance, in order to render the correct assortments, complex logic had to run in the Angular UI that took into account what was in our databases and combine it with what was in our users’ carts. In short, the UI was responsible for a lot of computationally intensive processes better left to backend services.

    Migrate your Angular components to React components

    Most likely there’s not going to be much overlap between how the Angular components were built and how the same component will be rebuilt in React with JSX. When recreating the components in the new app, study the functionality of how they behave currently and work with the user experience designers to ensure the new components recreate the functionality but also adheres to any larger UX organization best practices. It’s always beneficial to build similar workflows in apps within an organization so the actions feel more familiar to users.

    banner-cta-react-blue.webp

    Migrating from AngularJS to React - a real life example

    I’m sure at this point you’re wondering how my own team’s migration went. I’ll give you the highlights.

    After going through all the steps outlined in the previous section to evaluate our options, assess the risks, prove out our theory with a small proof of concept, and come up with a strategy for the migration (including rewriting logic in the AngularJS app into new supporting Java applications), we set to work.

    The full migration and eventual shutdown of our AngularJS app ended up taking 3 years. To accomplish this, we split the development team in two: half worked on migrating existing functionality to React, half worked on adding new features and functionality to React.

    By the end, there were 3 new Java microservices, 2 new databases, 1 new React application, and 1 slimmed down AngularJS application (this Angular app was a temporary addition).

    Progress was slower than expected. Extracting the business logic into standalone microservices took longer than anticipated, we went through 4 different databases before settling on a MariaDB, a subset of the development team was pulled away to assist setting up a new application to bring users who had been relying on Excel spreadsheets into the new millennium, and we also ended up building a thinned down AngularJS UI to test the new microservices before we’d recreated the functionality in React.

    It was tedious maintaining existing functionality while simultaneously removing all the twisting, turning, logic once needed in the UI to handle the data. But it was also beneficial, as we were able to identify gaps in the data that the microservices missed early on in the process and fix it.

    And in the end, it worked. The day the old AngularJS application was shutdown was a day when everyone breathed a sigh of relief.

    Closing Thoughts

    Rewriting an application in a new framework is not an easy undertaking, but in many cases it’s the best way forward when an important business application just can’t pass muster. It may be that long term support for the app’s current framework is ending, the app is getting slow for users and harder to maintain for developers, or functionality needed by the users just isn’t possible with the current technology.

    Whatever the reason, although it seems daunting, it is very possible: my own development team did it when we migrated from AngularJS to React. We mapped out a plan of attack beforehand, took a full assessment of our options, and built a proof of concept before we dove in. In the end, the migration was a success. Not everything went strictly to plan, but we were able to persevere and adapt as the migration progressed.

    This is certainly not the only way to approach such a migration, but I hope it gives you some points to keep in mind if you are faced with a similar situation.

    Good luck!

      We have more framework comparisons coming up. Subscribe so you don't miss out!
      Paige Niedringhaus

      Paige Niedringhaus is a former digital marketer turned full stack software engineer. She's currently enjoying developing enterprise level applications in Java and JavaScript's React framework. To see more of her blogs about technology and web development, you can visit her Medium profile here: https://medium.com/@paigen11

      ButterCMS is the #1 rated Headless CMS

      G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award G2 crowd review award

      Don’t miss a single post

      Get our latest articles, stay updated!