Evolving an AngularJS application (and what we can do after that)

How we started the evolution of our application built with AngularJS, Bower and Gulp to use Webpack.

João Fidellis
CWI Software
6 min readJul 17, 2019

--

The objective of this article is to explain how we started the evolution of our frontend application technologies, hoping it can help you to know the steps required to do it yourself. We will also discuss some cool things we can do after migration.

Before that, context about our project: it is a website with 3 years of development, built with AngularJS, TypeScript, SCSS and HTML. With more than 41 thousand lines of code.

We will talk about a tech migration done in a real-world application with a large codebase.

When I started in my first project as a front-end developer I was the “annoying” guy that asked why for everything (I’m still that guy, just a little experienced now).

Like every young developer, I wanted to work with the best and newest technologies out there, so, one day I asked “why AngularJS?”. The answer was pretty acceptable: when the project was conceived, the new Angular was in beta, and our client wouldn't like to use a stack in early development stage.

The Technical Leader of my project (Róbson Machado Rosa) saw my desire to evolve our technologies and challenged me to start it. He also gave me a hint about where to start my work: learn Webpack and get rid of Gulp.

Webpack and Module Resolution

So I went to the Webpack docs to learn its concepts and spent two weeks learning about the configs and trying them on our environment. After that, I had the first version of the configs, using awesome-typescript-loader (that wasn’t so awesome, more about that later 😂) to compile our TypeScript.

That was enough to start migrating from the old TypeScript global modules to the Webpack Module Resolution. We changed almost every TypeScript file in our project. My colleagues Júlia Vila, Cleber Hensel, and Alessandra Henkes helped with that.

Example of a service before and after the migration, with the changes highlighted (you may want to zoom in).

Adopting Babel and measuring build speed

While my colleagues were working on migrating the TS files, I was worried about the application’s build time.

The build time was around 50 seconds using the Gulp Tasks in the old version and increased to 140 seconds using the Webpack loaders 🐢. So I discovered the speed-measure-webpack-plugin. Exactly what I needed.

After installing the Speed Measure Plugin, it took only a few seconds to find my problem: the not-so-awesome awesome-typescript-plugin was taking an eternity to compile our TypeScript.

Lesson learned: remember to use a speed measure tool if you have performance issues with your plugins and loaders.

Meanwhile, my colleague Cleber Hensel was configuring Babel in our project so we could use some fancy and modern JS💛.

Example of the new code (left) and the old code (right). Bye callback hell!

I found out we could use Babel to compile our TypeScript as well. Bye 👋 to awesome-typescript-loader and hello to @babel/preset-typescript.

Result: build time fell to 37 seconds (not amazing, but not bad) and now we have fancy JS 🎉.

Bower and NPM

In the old version of our application, we had the majority of our dependencies installed through NPM, but, for some very specific reasons, some of them were installed using Bower. We had some work to move those dependencies to NPM, in order to get rid of Bower (who needs two package managers?).

Importing SCSS and images

We had a lot of work to make our SCSS correctly applied again. Webpack made our SCSS scoped, now we had to import the .scss files in the components that use them.

Since we already emulated scoping SCSS using classes, we had to go through every single file and update it, which wasn't difficult, but it took a long time to do.

Then we started to face another problem: images and SVGs in the HTML. Using absolute paths inside Strings in the HTML would not work anymore, since Webpack would not be able to find the referenced images.

The solution: AngularJS filters, as brilliantly thought by Júlia Vila 💁:

Using the filter (left), and the custom filter (right).

Honorable mention to our Quality Analysts ✔️

We changed a lot of our code, as you can see in our Merge Request.

I’m not kidding 😬

And that required a lot of testing, so I would like to give a shout-out to our QAs that worked side by side with us. They found exactly 29 bugs caused by our migration, and we were there on their side to fix them rapidly.

Considering that the number of changed lines of code sums to more than 25 thousand, we were expecting a large number of bugs, therefore to find only 29 bugs was surprisingly good (that is approximately 0.00011 bugs per line of code changed 😎).

The bug hunting team!

The Results

  • We now have an application written with ES7+ that is compatible with every significant browser version (thanks to Babel 💛);
  • We now use modern minification tools (UglifyJSPlugin) that, along with some code refactors, made our production build approximately 12% smaller than before;
  • Code Splitting and Webpack, have a lot of benefits: can be used to lazy load parts of the app 🎉 and make modules independent with dynamic imports!

What’s next?

A world of opportunities is ahead of us! And there is one thing that will help us with our next steps:

https://single-spa.js.org/

Single-spa is “a javascript framework for front-end microservices”. It was made to help you implement a Microfrontends Architecture. That may sound complicated, in fact it is, but without single-spa it would be a lot more.

Maybe we don’t really need to use this kind of advanced architecture in our app, but we surely can use him to gradually switch from our loved AngularJS to Angular ❤️, React 💙, or Vue 💚 (who knows?).

It will give us the power to deliver to production running two (or more 😱) frameworks easily, so that we won’t stop bringing value to our client while replacing frameworks.

That’s all we need to run our AngularJS application and some React components at the same time:

Looks cool right?

The end! 🙌

  • If you have any questions feel free to leave a comment, and I will answer in the best way I can;
  • If you are my work colleague and would like to talk, you can reach me on Slack (or rocket.chat)!

Thank you for your time!

--

--

João Fidellis
CWI Software

front-end focused, JS lover developer 👨‍💻