← all posts

Upgrading Angular from 13 to 21 with GitHub Copilot CLI

Gordon Beeming
Gordon Beeming
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

  1. A clean branch

Create a dedicated branch, and ideally tag/commit at each major version.

  1. A single build command you trust

For example:

Terminal
npm run build

If you have tests, even better:

Terminal
npm test
  1. 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):

Copilot CLI prompt
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:

Terminal
# Example: upgrade to Angular 14
npx -y -p @angular/cli@14 ng update @angular/core@14 @angular/cli@14 --force
npm install
npm run build

Repeat 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:

Error output
Unknown argument: prod

Fix:

package.json
// package.json
{
  "scripts": {
    "build": "ng build --configuration production"
  }
}

#2) Old dependencies that don't like modern Node

Common symptom:

  • node-sass install failures

Fix:

package.json
// 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
// 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:

Error output
"./dist/zone" is not exported from zone.js

Fix:

polyfills.ts
// 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:

Namespace import (before)
import * as dayjs from 'dayjs';

const d = dayjs();

A toolchain upgrade may reject calling that namespace import as a function.

Fix (default import):

Default import (after)
import dayjs from 'dayjs';

const d = dayjs();

Same idea for plugin imports:

Plugin import
import relativeTime from 'dayjs/plugin/relativeTime';
dayjs.extend(relativeTime);

#6) CSS import resolution changes (tilde ~)

If you have older Sass imports like:

Tilde import (before)
@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:

  1. git checkout -b upgrade/angular-13-to-21
  2. For each major version:
    1. npx -y -p @angular/cli@X ng update @angular/core@X @angular/cli@X --force
    2. npm install
    3. npm run build
    4. Fix errors (minimal)
    5. Commit: git commit -am "Upgrade Angular to X"
  3. 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.

Gordon Beeming
Gordon Beeming

Father • Husband • Triathlete • SSW Solution Architect

Related posts