Upgrading Angular from 13 to 21 with GitHub Copilot CLI
On this page5 sections ▾
I used GitHub Copilot CLI to help upgrade an Angular app from 13 to 21. I kept the work to one major version at a time and got the build working before moving to the next version.
That made dependency failures, removed build flags, and compiler changes easier to attribute to a particular upgrade. Copilot handled the repeated searches and edits, using the same build command after each change.
An upgrade from 13 to 21 is eight separate major-version upgrades. The workflow below keeps each one small enough to review.
#What you need before you start
- A clean branch
Create a dedicated branch, and ideally tag/commit at each major version.
- A single build command you trust
For example:
npm run buildIf you have tests, even better:
npm test- A known-good Node toolchain
Use nvm and pick a Node version that Angular supports.
#The workflow
Here's the loop I follow (and what I had Copilot CLI do for me).
#Step 0: Tell the AI what "done" means
Give the agent explicit limits: one version at a time, small changes, and a passing build before continuing.
Paste a prompt like this into Copilot CLI (I tested this with the GPT-5.2 model, but the structure matters more than the model):
I need help upgrading an Angular app from v13 to v21.
Rules:
- Do upgrades one major version at a time.
- After each upgrade, run `npm run build` and fix whatever breaks.
- Make the smallest possible changes.
- If you need clarification, ask one question at a time.
Start by checking the current Angular version and identifying the Angular workspace.Check that the agent starts by doing the following:
- identify the workspace (
angular.json) - confirm versions
- plan the upgrade path version by version
#Step 1: Upgrade one major version
I like this pattern because it makes the CLI version explicit:
# Example: upgrade to Angular 14
npx -y -p @angular/cli@14 ng update @angular/core@14 @angular/cli@14 --force
npm install
npm run buildRepeat for 15, 16, 17… until you reach 21.
#Step 2: Fix what breaks (keep it scoped)
Have the agent read the error, find the relevant code, apply a focused fix, and rebuild. Review that change before moving to the next upgrade.
#Common upgrade errors
The errors depend on the libraries and Angular features your app uses. These are examples to check when they appear.
#1) Deprecated/removed build flags
Example symptom:
Unknown argument: prodFix:
// package.json
{
"scripts": {
"build": "ng build --configuration production"
}
}#2) Old dependencies that don't like modern Node
Common symptom:
node-sassinstall failures
Fix:
// package.json
{
"devDependencies": {
// remove node-sass
// prefer sass
"sass": "^1.x"
}
}#3) The end of entryComponents
If you're coming from older Angular patterns, you might have modules like:
// app.module.ts
@NgModule({
declarations: [...],
entryComponents: [SomeDialogComponent]
})
export class AppModule {}In modern Angular, entryComponents is gone.
Fix: delete the property.
#4) Zone.js import changes
If your project still has old polyfill imports, you might hit errors like:
"./dist/zone" is not exported from zone.jsFix:
// polyfills.ts
import 'zone.js';#5) TypeScript/ESM import strictness
Modern Angular toolchains are pickier about import styles.
A common example is libraries that used to work with namespace imports:
import * as dayjs from 'dayjs';
const d = dayjs();A toolchain upgrade may reject calling that namespace import as a function.
Fix (default import):
import dayjs from 'dayjs';
const d = dayjs();Same idea for plugin imports:
import relativeTime from 'dayjs/plugin/relativeTime';
dayjs.extend(relativeTime);#6) CSS import resolution changes (tilde ~)
If you have older Sass imports like:
@import "~some-package/styles.css";Modern tooling may not support the ~ resolver the same way.
Fix: remove the ~ and use package exports (or the documented import path).
#7) New builder migrations and optional migrations
At some point, the CLI will offer migrations like:
- new build system / application builder
- template control flow syntax
Review what each migration changes before accepting it. Keep required upgrade work in the current step, and defer optional changes when they would make the diff harder to review.
#Keeping the agent focused
I use the agent for error triage, targeted edits, and repeated build checks. Keeping feature work and unrelated refactoring out of the upgrade makes the resulting diff easier to review.
#A repeatable checklist
Here's the copy/paste checklist I use:
git checkout -b upgrade/angular-13-to-21- For each major version:
npx -y -p @angular/cli@X ng update @angular/core@X @angular/cli@X --forcenpm installnpm run build- Fix errors (minimal)
- Commit:
git commit -am "Upgrade Angular to X"
- Final pass:
npx ng version- run the build/test pipeline you rely on
After the final upgrade, check ng version and run the build and tests you normally rely on. A successful build is a useful checkpoint, but the upgraded app still needs its usual behaviour checks.