Recently, Angular 20 has been released with tons of crazy cool features! While everyone’s talking about the major highlights, one of the less-discussed gems is the improved Angular Devtools that let you see simplified stats directly in Chrome DevTools.
I was super excited to try it out, but instead of starting a fresh Angular 20 app, I thought about the applications I published years ago - Jira Clone, Tetris, and Angular Spotify - that are still running on Angular 10 or so 😂. This is the perfect moment to upgrade them to Angular 20 and then explore all the new features!
So let’s start with migrating my Jira Clone from Angular 13 to Angular 20. Spoiler alert: it’s not as straightforward as I initially thought! 😅
First things first, I created a new branch to safely experiment:
git checkout -b trung/v20
Angular does an excellent job guiding us through the upgrade process. I visited angular.dev/update-guide and selected version 13 as the starting point (what Jira Clone is currently running) and version 20 as the target.
Initially, I thought Jira Clone was just a simple project that fetches data from a server and renders it on the client side. But the more I thought about it, I realized there were quite a few workarounds I implemented in Angular 13 to make certain features work. For example, I needed a custom webpack configuration to process SCSS files through postcss-loader
with several plugins:
{
test: /\.scss$/,
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
syntax: 'postcss-scss',
plugins: ['postcss-import', 'tailwindcss', 'autoprefixer'],
},
},
}
This meant the upgrade from Angular 13 to Angular 20 might not be as smooth as I initially anticipated. So I chose “Medium” application complexity to get notified about the tricky steps.
As you can see from the suggested steps, the safest route is to upgrade incrementally: 13 → 14 → 15 → 16 → 17 → 18 → 19 → 20
😂
In a real production application, you’d plan these upgrades in advance and tackle one version per sprint. But since this is my side project, I’m going to do it all in one weekend morning (that didn’t happen - I only managed to migrate to Angular 14 in one morning and a bit of night time 🤣)
Pro tip: After each upgrade step, test your changes and commit them if everything works. This way, if the next step fails, you can always roll back to the previous working version. Don’t try to do everything at once and commit at the end - you’ll never know which changes worked and which broke the upgrade.
I started with the Angular 14 upgrade:
ng update @angular/core@14 @angular/cli@14
Note: If you see the error zsh: command not found: ng
, it means you don’t have the Angular CLI installed globally. You have two options:
Install it globally (recommended for frequent Angular development):
npm install -g @angular/cli
Use npx (if you prefer not to install globally):
npx ng update @angular/core@14 @angular/cli@14
The npx
command allows you to run an arbitrary command from an npm package (either installed locally or fetched remotely). If ng
doesn’t exist on your machine, npm will fetch it from the registry and execute it.
I ran the command and immediately hit an error:
> npx ng update @angular/core@14 @angular/cli@14
The installed Angular CLI version is outdated.
Installing a temporary Angular CLI versioned 14.2.13 to perform the update.
✔ Package successfully installed.
Using package manager: npm
Collecting installed dependencies...
Found 70 dependencies.
Fetching dependency metadata from registry...
Package "@angular-eslint/schematics" has an incompatible peer dependency to "@angular/cli" (requires ">= 13.0.0 < 14.0.0", would install "14.2.13").
✖ Migration failed: Incompatible peer dependencies found.
Peer dependency warnings when installing dependencies means that those dependencies might not work correctly together.
You can use the '--force' option to ignore incompatible peer dependencies and instead address these warnings later.
The issue is that ESLint requires a specific Angular version. We have a chicken-and-egg problem: if we upgrade ESLint first, it will require Angular 14, but if we upgrade Angular first, ESLint will complain. The solution is to use the --force
option to proceed with the Angular upgrade first, then upgrade the dependencies.
After the Angular upgrade, I ran npm start
and immediately encountered another error:
This version of CLI is only compatible with Angular versions ^13.0.0 || ^13.3.0-rc.0,
but Angular version 14.3.0 was found instead.
Please visit the link below to find instructions on how to update Angular.
https://update.angular.io/
This was strange because the Angular CLI version was actually 14.2.13. I suspected the issue was with the @angular-devkit
versions. Even though @angular-devkit/build-angular
was at 14.2.13, other packages like @angular-devkit/core
and @angular-devkit/schematics
were still at 13.2.5.
To investigate which packages were using different versions of @angular-devkit/build-angular
, I ran:
npm ls @angular-devkit/build-angular
The output revealed the culprit:
[email protected] /Users/trung.vo/Source/jira-clone-angular
├─┬ @angular-builders/[email protected]
│ └── @angular-devkit/[email protected]
├── @angular-devkit/[email protected]
└─┬ @storybook/[email protected]
└── @angular-devkit/[email protected] deduped
The @angular-builders/[email protected]
was using @angular-devkit/[email protected]
, so we needed to upgrade it.
To see what versions were available for @angular-builders/custom-webpack
, I ran:
npm view @angular-builders/custom-webpack versions --json
The list was long, but I could use version 14.1.0
. To verify compatibility, I checked the peer dependencies:
npm view @angular-builders/[email protected] peerDependencies --json
Output:
{
"@angular/compiler-cli": "^14.0.0"
}
Perfect! We definitely have compiler-cli
14 in our project, so I updated the package.json
to use @angular-builders/[email protected]
.
After running npm install
again, I saw that @angular-eslint/[email protected]
also needed an upgrade.
I checked the available versions:
npm view @angular-eslint/schematics versions --json
There were many versions available up to 20, so I picked 14.3.0
and updated my package.json
.
Next, @ant-design/[email protected]
was causing issues. I followed the same process and checked available versions:
npm view @ant-design/icons-angular versions --json
I chose version 14.1.0
since it’s the closest version that should be compatible with Angular 14. I also noticed ng-zorro-antd
was on 13.1.0
, so I upgraded that as well.
Run npm install
again and now @sentry/[email protected]
was throwing an error - which was expected! 😄 The tricky part with Sentry is that it doesn’t follow Angular’s versioning pattern (13, 14, etc.). Instead, it uses its own versioning like 6.18.1, so the next version that supports Angular 14 would likely be version 7.
I checked the available Sentry versions:
npm view @sentry/angular versions --json
Wow, there were many versions! Sentry doesn’t jump per major version as you might expect. I searched for @sentry/angular compatible with angular 14
and found comprehensive documentation from Sentry:
In its current major version, the Sentry Angular SDK supports Angular 14 and newer.
If you’re using an older version of Angular, you also need to use an older version of the SDK. See the table below for compatibility guidance
I had two options:
npm install @sentry/angular@latest --force
(we need --force
because our dependencies aren’t fully resolved yet due to the Sentry package itself)npm view
outputI chose option 2 and picked version 9.30.0
. To be safe, I checked the peer dependencies first:
npm view @sentry/[email protected] peerDependencies --json
Excellent! The peer dependencies were quite broad: >= 14.x <= 20.x
, so we were safe to proceed.
Pro tip: npm view <package name> peerDependencies --json
is the way to verify package dependencies without going to the npm website or “guessing”!
Finally, npm install
worked! I ran npm start
and the application finally started building.
However, there was still a Sentry error preventing the app from starting:
Since the issue was isolated to Sentry, I temporarily commented out the problematic code. The app compiled successfully!
👉 I opened this PR here: https://github.com/trungvose/jira-clone-angular/pull/105
This was just the first step - upgrading to Angular 14. The journey continues with upgrades to versions 15, 16, 17, 18, 19, and finally 20. Each step will likely bring its own challenges and dependencies to resolve.
The key takeaways from this Angular 14 upgrade:
--force
when dealing with peer dependency conflicts during major version upgrades, but make sure to resolve all dependencies before merging to the main branch. Otherwise, CI builds and other developers’ machines will fail to run npm install
and they’ll also need to use --force
npm view <package> versions --json
npm view <package> peerDependencies --json
Stay tuned for the next part where we upgrade Angular 15!