There are many options you can use when upgrading an Angular application, and the decision of which to choose should be made primarily on the effort, time and skill sets available within the team. Otherwise, the process could be catastrophic to the project. In this article, I’ll share what I’ve learned through my experience when it comes to upgrading an AngularJS application to Angular 7.
About a year ago, I joined a team that had already been building a new online banking platform for a bank’s offshore customers. They had been doing so for about a year and a half, with nothing going to production for general use by the public. It turned out that I was in for quite a shock. Their operation had a few core drawbacks:
- The development process was slow without any HML (Hot Module Reload) mechanism present. In other words, every single change made during development required a manual recompile in order to test the changes made.
- The morale of the team was constantly at risk because the re-compiling and running of the project took out a large chunk of time from the day. We felt like we were wasting our time, waiting for the application to reload just to test that the changes we made didn’t break existing functionality.
- This would lead to very low quality unit and acceptance tests.
- And that lead to bugs returning more frequently, from our beta testers back to the developers. We were basically a bug fix team more than a product team.
- So, in general, motivation for the project was at an all time low.
Because of the hybrid state we were in, our project was slow to respond to user input, and had an overall bad user experience. Simply put, it was very difficult to effectively develop on.
The team was also in the process of upgrading the web application from an AngularJS framework to the more modern Angular framework. When I initially joined, a decision had already been made to start the upgrade process of the application by using a hybrid state on the application.
At the time, their thinking was that this would be the fastest way to upgrade the project without losing existing functionality, and deploy the project to production for general public-use as soon as possible.
Using the NgUpgrade module
When upgrading an Angular application, there are two major ways that you can systematically convert your existing components: Either, so that they work with the newer Angular, or so that the new Angular components work with the older AngularJS framework. These approaches are made possible by an Angular module called NgUpgrade, which helps ease the pain of transitioning to the newer Angular framework from AngularJS.
With the NgUpgrade module, you can write a component in the new Angular framework syntax, Typescript, and simply wrap it in an AngularJS component using
downgradeModule(…) functions. This is the exact approach our team thought would be the best to quickly and reliably upgrade the project.
The caveats of this approach, however, were two-fold:
Huge amount of additional code
The amount of additional code that was required to wrap the upgraded instances into the older framework ultimately lead to bugs creeping into the platform more easily. The testing of our application was an even more painful process to get through: Our unit tests had to cover not only the functionality of the components we were writing, but also the wrapper instances of the upgraded components.
The different ways that the old AngularJS framework and the new Angular framework compile their final view, meant that we had to have duplicate selectors for common components when it came to writing acceptance tests. More code, meant more bugs.
Decline in team morale
A difficult development environment meant the developers got understandably fed up with the project quite quickly. Overall, team morale dropped. As a result, developers were starting to look at better options, and so started our high turnover of developers on the project.
The problem with this situation was the loss of crucial business knowledge. Getting that knowledge back, or having to now learn it, took time. We ended-up losing even more development time, barely ever achieved our goals, and business clients started getting really frustrated.
Rewriting into the new framework
Due to the difficult development environment and extremely low team morale, we as the developers realised two things: Our current approach to upgrading the project was not sustainable, and we would never be fully completed if we continued with the AngularJS and Angular hybrid upgrade strategy.
So, we started rewriting the entire application over into the new Angular framework in our spare time, to show our business that there was value in re-writing the whole platform. We knew they would not easily buy into this approach if we didn’t show them why it was important.
After having the basic functionality of the platform completely rewritten and implemented into the new framework, we demoed the new project. It became immediately clear to them why we had to focus on the rewrite instead of the hybrid state application.
These are a few of the reasons why:
|Considerations||AngularJS + Angular Hybrid||Angular 7|
|Development time||No CLI, so hooking up the components into the application was very much a slow, manual process. A lot of wrapper code for upgraded components and modules.||Faster due to the Angular CLI which did all the nitty gritty work for us, so we could focus on writing feature functionality.|
|State management||RXJS was fairly new when the development began, so most state management and message passing was created by the developers themselves. This was buggy and unnecessarily complicated, and didn’t conform to the Redux pattern.||Better state management with the use of the NGRX library. This meant we had a single store, we could isolate side effects, and we could finally use the Redux DevTools extension to help us debug our state management.|
|Compiling||Compilation took quite a bite out of our time, since the compilation needed to take into account the upgrade modules as well as the older framework.||With hot module reloading, compilation was almost instant and testing of the design and functionality was extremely fast.|
|End-user experience||Since there was so much context-switching and no lazy-loading of modules available in this hybrid state, the entire application needed to be downloaded before the user could use it. The application was slow with navigating between different pages.||The functionality was smooth and the end product had less bugs, so the user experience was much better than the hybrid state platform. With the new framework and its set of tools, we could better manage which components needed to be downloaded to the client with lazy loading, and when. This increased the speed at which the application is made available to the end-user.|
After seeing the issues with the hybrid state application, and the immense value the rewrite would have to their customers, we were finally given the green light to focus on the rewrite, and could finally start the depreciation of the old AngularJS/Angular hybrid platform. There was a very visible morale boost within the team.
Feature development, which previously took us months, was now easily being done within a two-week sprint.
What I learned
Being on this project threw me in the deep end, and has taught me quite a lot:
- How to manage business expectations: The upgrade process in a hybrid state is quite lengthy and thus I needed to learn how to manage business expectations really well to be able to deliver new features, upgrade old components and fix bugs on existing components.
- How to cope with a lack of leadership: During development, the technical decisions were made by us, as the developers, without the insight from a tech lead. This taught us how to strengthen the communication within the team, and about understanding and debating code and solution design criticism.
- Why hybrid solutions are generally rubbish: Most importantly, I had learned that when choosing to upgrade an AngularJS application to Angular, the only way to go about it is to rewrite the application. Never, ever, go with a hybrid solution!
Implementing the hybrid solution when upgrading an AngularJS to Angular application is simply inefficient. It takes a long time to develop, and as a result could cost the business valuable money. Rewriting sounds like a much lengthier process, but in our case it turned out to be much faster, and produced a much more stable and reliable product to the end-user. It was more beneficial to us, to our clients, and inevitably to their customers.
Jason Evans completed his BSc(Hons) Computer Science degree at the University of Pretoria in 2016, and has been a Golden Key Honours Society member since 2017. Currently, he is working as a software engineer at Entelect. You can start a conversation with him on his LinkedIn or Twitter, or go straight to his website!