Angular is on a six-month release cadence, which means you need to stay on top of them in your own projects. The last thing you want to do is wake up one day and find that the latest version was just released and you are stuck on a version from two and a half years ago. Fortunately, the Angular team has made it very easy to upgrade.
Official Upgrade Guidance
Did you know that Angular offers official upgrade guidance? If you have not seen the website, take a look here at the Angular Upgrade Guide.
My Project
The project I am upgrading is the demo application presented in my book and course on Ionic and Angular development. You can find both at Gumroad.
The application itself is an Ionic app, written to run equally well on both desktop and mobile devices.
At the time I began, it was an Angular 8 app that had been automatically generated by the Ionic CLI.
You can see the app as it was just before I started the upgrade at its public GitHub repo.
I do not want it to fall too far behind, so I decided I should upgrade it to Angular 10 and make sure it works.
Angular 8.x to 8.y
The first thing I did was make sure the project was on the latest version of Angular 8. I did this by first making sure I had a clean repo (I did) and then entering the following command (and its output):
npx ng update @angular/cli@8 @angular/core@8
The installed Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Using package manager: 'npm'
Collecting installed dependencies...
Found 35 dependencies.
Fetching dependency metadata from registry...
Package '@angular/core' is already up to date.
Updating package.json with dependency @angular-devkit/build-angular @ "0.803.29" (was "0.803.25")...
Updating package.json with dependency @angular/cli @ "8.3.29" (was "8.3.25")...
UPDATE package.json (1619 bytes)
✔ Packages installed successfully.
I specifically asked the CLI to update to @angular/cli and @angular/core version 8, which will update to the most recent minor/revision available to that major version.
I used npx
to use the local Angular CLI version in the project. As you can see from the warning that it had its own idea and installed a temporary version to perform the update.
Apparently I was pretty close to current on Angular 8. It did not do much.
Next, I committed the code. Angular will not update on an unclean working repo.
git commit -am "Updated to latest Angular 8"
[master e9e9c71] Updated to latest Angular 8
2 files changed, 3429 insertions(+), 2214 deletions(-)
You can compare what changed by reviewing the diff on GitHub. Again, not much happened.
Angular 8 to Angular 9
Next, I upgraded the project to Angular 9, with this command (it should look familiar).
npx ng update @angular/cli@9 @angular/core@9
This command did a lot more than the last one because now we are looking at an update of a major version.
Here is the output:
The installed Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Using package manager: 'npm'
Collecting installed dependencies...
Found 35 dependencies.
Fetching dependency metadata from registry...
Updating package.json with dependency @angular-devkit/build-angular @ "0.901.12" (was "0.803.29")...
Updating package.json with dependency @angular/cli @ "9.1.12" (was "8.3.29")...
Updating package.json with dependency @angular/compiler @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency @angular/compiler-cli @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency @angular/language-service @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency typescript @ "3.8.3" (was "3.4.5")...
Updating package.json with dependency @angular/common @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency @angular/core @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency @angular/forms @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency @angular/platform-browser @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency @angular/platform-browser-dynamic @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency @angular/router @ "9.1.12" (was "8.2.14")...
Updating package.json with dependency zone.js @ "0.10.3" (was "0.9.1")...
UPDATE package.json (1620 bytes)
✔ Packages installed successfully.
** Executing migrations of package '@angular/cli' **
❯ Update an Angular CLI project to version 9.
UPDATE angular.json (5386 bytes)
Migration completed.
** Executing migrations of package '@angular/core' **
❯ Static flag migration.
Removes the `static` flag from dynamic queries.
As of Angular 9, the "static" flag defaults to false and is no longer required for your view and content queries.
Read more about this here: https://v9.angular.io/guide/migration-dynamic-flag
Migration completed.
❯ Missing @Injectable and incomplete provider definition migration.
In Angular 9, enforcement of @Injectable decorators for DI is a bit stricter and incomplete provider definitions behave differently.
Read more about this here: https://v9.angular.io/guide/migration-injectable
Migration completed.
❯ ModuleWithProviders migration.
In Angular 9, the ModuleWithProviders type without a generic has been deprecated.
This migration adds the generic where it is missing.
Read more about this here: https://v9.angular.io/guide/migration-module-with-providers
Migration completed.
❯ Renderer to Renderer2 migration.
As of Angular 9, the Renderer class is no longer available.
Renderer2 should be used instead.
Read more about this here: https://v9.angular.io/guide/migration-renderer
Migration completed.
❯ Undecorated classes with decorated fields migration.
As of Angular 9, it is no longer supported to have Angular field decorators on a class that does not have an Angular decorator.
Read more about this here: https://v9.angular.io/guide/migration-undecorated-classes
Migration completed.
❯ Undecorated classes with DI migration.
As of Angular 9, it is no longer supported to use Angular DI on a class that does not have an Angular decorator.
Read more about this here: https://v9.angular.io/guide/migration-undecorated-classes
Migration completed.
Your project has been updated to Angular version 9!
For more info, please see: https://v9.angular.io/guide/updating-to-version-9
There were some warnings, which I will take care of eventually. For now, they did not affect the application. I then committed the changes.
git commit -am"Upgraded to Angular 9"
[master ba20fd7] Upgraded to Angular 9
3 files changed, 3695 insertions(+), 2830 deletions(-)
The GitHub diff is here.
The only thing of note that it changed was that it added this bit of JSON to the angular.json file:
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
Angular 9 to Angular 10
Finally, I let the CLI upgrade from Angular 9 to Angular 10.
npx ng update @angular/cli @angular/core
The installed local Angular CLI version is older than the latest stable version.
Installing a temporary version to perform the update.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
Using package manager: 'npm'
Collecting installed dependencies...
Found 35 dependencies.
Fetching dependency metadata from registry...
Updating package.json with dependency @angular-devkit/build-angular @ "0.1001.7" (was "0.901.12")...
Updating package.json with dependency @angular/cli @ "10.1.7" (was "9.1.12")...
Updating package.json with dependency @angular/compiler @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency @angular/compiler-cli @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency @angular/language-service @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency typescript @ "4.0.3" (was "3.8.3")...
Updating package.json with dependency @angular/common @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency @angular/core @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency @angular/forms @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency @angular/platform-browser @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency @angular/platform-browser-dynamic @ "10.1.6" (was "9.1.12")...
Updating package.json with dependency @angular/router @ "10.1.6" (was "9.1.12")...
UPDATE package.json (1620 bytes)
✔ Packages installed successfully.
** Executing migrations of package '@angular/core' **
❯ Missing @Injectable and incomplete provider definition migration.
As of Angular 9, enforcement of @Injectable decorators for DI is a bit stricter and incomplete provider definitions behave differently.
Read more about this here: https://v9.angular.io/guide/migration-injectable
Migration completed.
❯ ModuleWithProviders migration.
As of Angular 10, the ModuleWithProviders type requires a generic.
This migration adds the generic where it is missing.
Read more about this here: https://v10.angular.io/guide/migration-module-with-providers
Migration completed.
❯ Undecorated classes with Angular features migration.
In version 10, classes that use Angular features and do not have an Angular decorator are no longer supported.
Read more about this here: https://v10.angular.io/guide/migration-undecorated-classes
Migration completed.
As before, I committed the code and checked the behavior of the application.
git commit -am"Upgraded to Angular 10"
[master a0114c1] Upgraded to Angular 10
2 files changed, 1945 insertions(+), 897 deletions(-)
The GitHub diff is here. As you can see, it only updated packages. Though it showed many of the same warnings, it did not find anything in the code it needed to migrate.
As I reviewed those migration guides, I also did not find any issues to update. I cannot confirm this, but I believe that the Ionic team keeps on top of these things and uses the latest Angular guidance in their application generators.
Summary
Will your upgrade go as smoothly? I cannot guarantee it, of course. Honestly, the application is modest enough that I did not expect any problems.
As a convenient summary, here the commands I used (without the command output being shown).
npx ng update @angular/cli@8 @angular/core@8
git commit -am "Updated to latest Angular 8"
npx ng update @angular/cli@9 @angular/core@9
npx ng generate component Loading --spec=false --dry-run\n
git commit -am"Upgraded to Angular 9"
npx ng update @angular/cli @angular/core
git commit -am"Upgraded to Angular 10"
As I said, your experience may not be the same as mine. You may not even need npx
. I hope this article helped you, even a little, and I wish you every success in your own endeavors.
Angular Advocate
If you are interested in more content like this, please consider my recently-released book, Angular Advocate: How to Awaken the Champion Within and Become the Go-to Expert at Work, available in a Print and Kindle Edition at Amazon or DRM-free on Gumroad.
Do you have any comments, questions, or just want to see more? Please follow me on Twitter and let me know.
Did I make any mistakes in this post? Feel free to suggest an edit.