Upgrade of production app from Angular 4 to Angular 7 — Be up to date with new tech

Nikola Tasikj
Web Factory LLC
Published in
9 min readJul 30, 2019

Progressive technology

We are lucky to live at a time when technology is really progressive. Every day there are some new tools that are helping us with developing. Recently there was an Angular 8 release, with the announcement of the new Ivy compiler, but what use do we have from it if we can’t use it on our projects? There are a lot of legacy projects where Angular version is below 7 and because of that we can’t try new features that make the apps run faster, smoother and are easier and more fun to use. Learning new things is always funny, so because of that don’t be scared to upgrade your old projects into new that will be up to date with new technologies.

Overcome your fear from upgrades

A lot of developers are “scared” of doing any kind of refactor or upgrades, because there is always a high chance of breaking something that worked before. But, how can be one project sustainable if we don’t maintain it? So, you need to be happy when your project manager will give you enough time to do some refactor or to upgrade your project. I will give you few small tips that I learned when me and the team upgraded one of our big 3-years project from Angular 4 to Angular 7. Yea it’s a big step because we are jumping 2 versions, but it was totally worth it. This process to be easier for understanding, you should open some kind of logs document where you will put all actions you have taken.

Start from scratch — get full control of your project

Each one of us wants just to type a couple of commands in terminal and to wait “magic” to happen, but it’s not always that easy.
Due to so many limitations the first versions of Angular CLI, our project till recently was an ejected app with own webpack configuration. However, we’ve been following the development of the new features of the CLI and decided it’s time to add it back to our project and make a lot of things easier for us. How we did this? We created new Angular 7 project with default settings.

Angular CLI is the biggest reason why we did this upgrade. Everything is easier with CLI, creating new files (components, modules, services) with schematics can be done with using only one command as ng generate component [name]. Also, all your settings will be easier to manage through angular.json file and CLI will take care for compiling all your .js and .js.map files, so you can be focused only on writing code in .ts files. Setting testing environment like Karma & Jasmine was really painful with webpack, but now CLI will take care of it for you.

So, before starting this process upgrade your global nodeJS and Angular versions. Here you can find tutorial how to upgrade your NodeJS and upgrade global Angular with commands:

npm uninstall -g angular-cli
npm cache clean or npm cache verify #(if npm > 5)
npm install -g @angular/cli@latest (You will specify in your project which version to use)

Couple of steps that we will follow:

  • Create new project
  • Import all old files and settings
  • Check and delete all unused dependencies and settings — mostly webpack
  • Update all old npm packages that are not compatible with new Angular 7
  • Install rxjs-compat
  • Set environment variables
  • Fix a lot of errors that happened because of AOT (Ahead Of Time) compiler
  • Code versioning

Importing all old files and settings — copying is part of our job everyday :)

This is maybe one of the easiest part in this upgrade. All you need to do is to go in your src folder (or if you have something outside) in your old application and to copy all files into new created Angular 7 project. With this you will keep all your data, structure and settings same as before.

Check and delete all unused dependencies and settings — mostly Webpack

In our case, most likely in your too, we used a lot of custom webpack settings to keep building/compiling process clean and easy. In your new Angular 7 project you will not need it, because Angular CLI has webpack configuration “under the hood” and you don’t need to specify any settings for it. Of course there is a way to do custom settings for webpack if you need it (check angular builders), but we don’t need them for now. Angular CLI comes with an angular.json file where you can see or set all settings for building/compiling your project. It looks like:

Also we had some npm packages that are linked to webpack, so the best way for you is to go through all dependencies in your package.json and to clear all unused ones, one by one. This is a long and not an easy process, but your node_modules will be smaller and that will help you with faster build.

Update all old npm packages that are not compatible with new Angular 7 — the hardest part

If you came this far that means you successfully started this process and you reached the hardest part. Now you need to run your project for first time with simple ng serve command and you will get a very long list of red characters — errors, but don’t worry it’s normal. This is part where most of us will give up, disappointed from a lot of errors that appeared, but don’t be one of them because every error has a solution! You will need to analyze every single error separately to find where does it come from and what need to be changed.

Let me explain why is this needed. Every npm libary has a specific version and they are maintained by their publisher, so if you installed some library in Angular 4 a long ago that version was built for that specific Angular, but with the updates of the framework, libraries also need to be up to date with the latest changes. So, if you are a couple of major versions behind, most likely that a lot of methods or implementation are changed, so you will need to update it to work with new Angular 7 project and to change some code implementation. Also, they need to be compatible with AOT compiler, but i will talk about it later.

Please keep in mind that you will need minimum v3.1 of Typescript for Angular 7.0. Here is a list of libraries that we updated to new version, it was not an easy job and it took us quite few days with a lot of researching and error fixing, but don’t give up!

Updated npm packages

Install rxjs-compat — prevent changing syntax in every component

With new version 6 of RxJs came one really big change that affected all older applications. The way of chaining operators was crucial for all RxJs users. Instead of old chaining way they put all operators in pipe(). So, to update your RxJs to 6 and to avoid going through all components where you will need to change syntax, you can simply use rxjs-compat and keep the existing code. This really helped us because we solved one really big problem.

This is not permanent solution because you will need to do new implementation that will affect speed and readability of your application, but not everyone have that much time for upgrade and will leave this for later.

Set environment variables

One of the problems appeared in phase where we got some version that is compiling on localhost without AOT. When we want to test it on production environment (not actually production, but development server with production environment) we were thinking how to hide environment variables, because pushing them on git is not that good idea, especially not staging/production variables.

When you host your application somewhere, in our case Heroku, you can set variables there. Those variables will be available in Node’s process.env runtime, but you need to fetch them while application is building and save them somewhere in your application from where you will using them runtime.

One way to do this is to create a script on root level that will fetch all variables from process.env and put them in your environment.ts. This script will be called from package.json after build. Here is an example

after that you can put script in your package.json something like

“heroku-postbuild”: “npm run config && ng build — prod”

Fix a lot of errors that happened because of AOT

If you want to use advantages of new Angular you need to enable build optimizations and AOT compiler, they are enabled by default. Here you can read more about AOT.

The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code. Sometimes this is a problem, because Angular needs to know about every variable, from where to bind it in HTML file, if there are some typos like using private variable in the HTML file, Angular will get confused and will throw an error about this things. Don’t worry if you run your application in AOT and get a lot of errors, most of the time they are typos and easy to fix. Here is an example of what you can expect when you run your project with AOT compiler.

Those fixes are really small and easy, all you will need to do is to go in some component to change variable from private to public, to check and fix your models with proper attributes, etc.

Code versioning

The best solution was to stop with development and work only on upgrade of the project, but we all know that this is not possible scenario on Agile projects.
So instead we created new project with separated git file and we faced the problem of not having the commits history of our project. This lead to what we should have done in the first place, and that is creating a new branch, adding all new configuration files in it and after that make the needed changes in code.

Keep going…

What is benefit of upgrading your application?

New is always better than the old one, your application will be faster, optimized, minimized and a lot of possibilities for integration with new libraries will be open. Don’t stop here, if you upgraded your application to use Angular 7 instead of 4 you need to use its benefits, if you stop here it will be same as before, but few seconds faster. Couple of things that you can do:

  • Change all imports of whole library (like lodash and RxJs) to import only needed modules/functions. For lodash you can use lodash-es where you can import functions like import isEqual from ‘lodash-es/isEqual’ and for RxJs you have possibility to import like import {Observable} from “rxjs/Observable”. Never import the whole library like import * as _ from ‘lodash’
  • Fix references to node_modules in .scss files. Instead of using multiple ../../.. in path, use ~ like import “~node_modules/x/whatever.css”
  • If your application is large, most likely you will have problem with javascript heap memory when you will try to build it. This is most likely because of big node_modules, you need to keep packages clean, not to install npm package for every function that you can actually write a code for. Temporary solution for this will be node — max-old-space-size=4096 ./node_modules/@angular/cli/bin/ng build that will build application with bigger memory for node_modules.
  • Compress your assets
  • Keep your application up to date with new technology

Thanks for reading, if you have some problems (you will) feel free to ask in comments.

--

--