Downhills of updating enterprise-sized Angular application

In the past, in my company, we used AngularJS as our frontend framework. Last year we started writing new functionalities in the latest then Angular version - 10. Time flies, and no one was thinking about updating the framework itself and its dependencies. However, a few weeks ago I tried to use a feature from CDK that turned out to be newish. So I decided to went through it, and it was one hell of a ride.

The first trouble

Angular developers maintain an interactive update guide, which provides steps to update an app. At first glance, it looks very detailed, so I was confident about the process. It took shorter than I thought for a reality check. After updating to version 11, some of the stylings just disappeared. It took me an embarrassingly long time to come up with that these are the global styles. We are using the new Angular part as an iframe in the old application. Because of that, we have a slightly modified developer environment. New versions of Angular don't extract CSS to JS to HMR them. That fact caused that the app couldn't load the "styles.js" file because there was none. It sounds stupidly easy to find and debug. Even though, as I admitted, it took me about an hour. And it was just the beginning.

Guide shortcomings

Reality often verifies our confidence and thoughts. This time it turned out that guide is not so detailed and complete as I was thinking. Not all of the breaking changes were there. For example, the syntax for binding CSS variables binding using the style directive changed between the Angular 10 and 11 versions. What is even worse - I couldn't even find the related issue to find out the solution. 

Moreover, instruction about updating Angular comes down to "ng update @angular/material@11". Unfortunately, it's not so easy sometimes. Upgrading to version 11 caused the change of box-sizing to Material inputs. What seems like a relatively small change is time-consuming to fix without globally applying previous value back. However, I didn't want to fall back to the second solution as this change was due to the bug. 

Human factor

Unfortunately, developers aren't always use everything as it was supposed to. They often tend to come up with some hackish solutions. These hackish solutions are the ones that like to break after minor updates. Or they write straight-up nasty code. For example, in one of the components, spacing around checkboxes got larger after the Material update. After looking into it turned out that margins were there before but weren't applied because the checkbox was inline, so it had default spacing. Moreover, many dependencies weren't even actively maintained even back then. Now searching for replacements was a nightmare. 

Yet, the biggest problem was our monolithic project structure. New versions of Angular Material use the SASS compiler written in Dart and its corresponding JavaScript port. But when I updated the SASS package, it somehow still found "node-sass". The reason was in the parent directory, where the AngularJS part sits. Somehow the compiler still was using the old compiler taken from the precursor dependencies. So I was forced to update it and everything related to it in the old app.

The end of the journey

So after few days of playing with it and fixing various bugs found by me and QAs, it was over. And the most important thing that I learned through it was how easy it's to do it regularly. Updating dozens of dependencies is immeasurably frustrating. Most of the components can and probably will break. However, we can make it infinitely easier by doing it more habitually.