chore: upgrade to Angular v22 + latest Nx #219

Closed
opened 2026-06-08 17:13:08 +00:00 by spikerj · 5 comments
Owner

Goal

Upgrade the workspace to the latest Angular and Nx.

Current vs. target

Package Current Target
@angular/* (core/cli/material/cdk/ssr/…) ~21.2.x ~22.0.x
nx / @nx/* 22.7.2 22.7.5
ng-packagr 21.2.x 22.0.x
TypeScript 5.9.3 as required by Angular 22 (≤ 6.0)

Plan

  1. Branch off master.
  2. nx migrate to Nx latest and Angular 22, review the generated migrations.json.
  3. Run the migrations (codemods: SSR import moves, tsconfig module/moduleResolution/lib updates, unit-test runner option, ESLint package bumps, etc.) and install.
  4. Resolve any breaking changes across apps + the ~37 libraries.
  5. Verify: build the main app, run the unit suites, and lint.
  6. Open PR; close this ticket on merge.

References

Risks / watch-list

  • TypeScript 6.0 compatibility (may need to stay on 5.9 if Angular 22 doesn't yet support TS 6).
  • Third-party Angular libs that peer-depend on Angular (keycloak-angular, ng-qrcode, ngx-mask, ngx-extended-pdf-viewer, @fortawesome/angular-fontawesome, @storybook/angular, rete-angular-plugin, @fullcalendar/angular) may need their own bumps.
  • The @angular/build:unit-test (vitest) setup and the recently-fixed jsdom Web Storage shim.
## Goal Upgrade the workspace to the latest **Angular** and **Nx**. ## Current vs. target | Package | Current | Target | |---|---|---| | `@angular/*` (core/cli/material/cdk/ssr/…) | `~21.2.x` | `~22.0.x` | | `nx` / `@nx/*` | `22.7.2` | `22.7.5` | | `ng-packagr` | `21.2.x` | `22.0.x` | | TypeScript | `5.9.3` | as required by Angular 22 (≤ 6.0) | ## Plan 1. Branch off `master`. 2. `nx migrate` to Nx latest **and** Angular 22, review the generated `migrations.json`. 3. Run the migrations (codemods: SSR import moves, tsconfig `module`/`moduleResolution`/`lib` updates, unit-test runner option, ESLint package bumps, etc.) and install. 4. Resolve any breaking changes across apps + the ~37 libraries. 5. Verify: build the main app, run the unit suites, and lint. 6. Open PR; close this ticket on merge. ## References - Angular v22 release: https://angular.dev/events/v22 - Nx Angular migrations: https://nx.dev/docs/technologies/angular/migrations ## Risks / watch-list - TypeScript 6.0 compatibility (may need to stay on 5.9 if Angular 22 doesn't yet support TS 6). - Third-party Angular libs that peer-depend on Angular (`keycloak-angular`, `ng-qrcode`, `ngx-mask`, `ngx-extended-pdf-viewer`, `@fortawesome/angular-fontawesome`, `@storybook/angular`, `rete-angular-plugin`, `@fullcalendar/angular`) may need their own bumps. - The `@angular/build:unit-test` (vitest) setup and the recently-fixed jsdom Web Storage shim.
Author
Owner

Status: BLOCKED — on hold pending Nx support for Angular 22.

Investigation (2026-06-08)

  • Latest Angular = 22.0.0; latest stable Nx = 22.7.5 (workspace is on 22.7.2).
  • nx migrate @angular/core@22 @angular/cli@22 bumped only the Angular runtime packages and deliberately left the build tooling (@angular/cli, @angular-devkit/*, @angular/build, ng-packagr, @schematics/angular, Material/CDK) at 21.2.x.
  • Root cause: @nx/angular@22.7.5 peer dependencies cap the build tooling below 22:
    • @angular/build: >= 19.0.0 < 22.0.0
    • ng-packagr: >= 19.0.0 < 22.0.0
    • @schematics/angular, @angular-devkit/{core,schematics,build-angular}: >= 19.0.0 < 22.0.0
  • Pre-release Nx lines were also checked: next (23.0.0-beta.24) and canary still cap @angular/build < 22.0.0.

Conclusion

No released or pre-release version of Nx supports Angular 22 yet, so a clean upgrade isn't possible. Forcing it would require pnpm peer-dependency overrides and running Angular 22's build through an unsupported @nx/angular, which risks broken builds and the @angular/build:unit-test runner.

Decision

Hold. No code changes made (the exploratory branch was discarded). Re-attempt once Nx ships an Angular 22 support release (typically a few weeks after an Angular major). At that point: nx migrate latest should bump both cleanly.

**Status: BLOCKED — on hold pending Nx support for Angular 22.** ### Investigation (2026-06-08) - Latest Angular = `22.0.0`; latest stable Nx = `22.7.5` (workspace is on `22.7.2`). - `nx migrate @angular/core@22 @angular/cli@22` bumped only the Angular **runtime** packages and deliberately left the build tooling (`@angular/cli`, `@angular-devkit/*`, `@angular/build`, `ng-packagr`, `@schematics/angular`, Material/CDK) at `21.2.x`. - Root cause: `@nx/angular@22.7.5` peer dependencies cap the build tooling below 22: - `@angular/build`: `>= 19.0.0 < 22.0.0` - `ng-packagr`: `>= 19.0.0 < 22.0.0` - `@schematics/angular`, `@angular-devkit/{core,schematics,build-angular}`: `>= 19.0.0 < 22.0.0` - Pre-release Nx lines were also checked: **`next` (`23.0.0-beta.24`)** and **`canary`** still cap `@angular/build < 22.0.0`. ### Conclusion No released or pre-release version of Nx supports Angular 22 yet, so a clean upgrade isn't possible. Forcing it would require pnpm peer-dependency overrides and running Angular 22's build through an unsupported `@nx/angular`, which risks broken builds and the `@angular/build:unit-test` runner. ### Decision Hold. No code changes made (the exploratory branch was discarded). Re-attempt once Nx ships an Angular 22 support release (typically a few weeks after an Angular major). At that point: `nx migrate latest` should bump both cleanly.
Author
Owner

Framework major upgrade — coupled dependency set + unblock note

While triaging package.json for outdated libs, I split the safe / non-framework upgrades into their own tickets (#229 #230 #231 #232 #233 #234). Everything below stays here because it's part of the one coupled Angular/Nx jump and must move together:

Package(s) Current Target
@angular/* (core, common, compiler(-cli), forms, router, animations, elements, material, cdk, aria, google-maps, platform-*, service-worker, ssr, language-service) 21.2.x 22.0.1
@angular-devkit/*, @schematics/angular, @angular/cli, @angular/pwa 21.2.11 22.0.1
ng-packagr 21.2.3 22.0.0
@angular-eslint/* + angular-eslint 21.4.0 22.0.0
@nx/* + nx 22.7.2 23.0.0
eslint 9.39.3 10.5.0 (needs angular-eslint 22)
typescript 5.9.3 6.0.3 (Angular 22 supports TS 6)
keycloak-angular 21.0.0 22.0.0 (verify Angular peer)

Unblock note (the premise changed)

Nx 23.0.0 was released 2026-06-16 and adds Angular 22 support. Per the Nx ↔ Angular version matrix, Angular 22 pairs with Nx 23 (latest). So the earlier blocker (“Nx latest doesn't support Angular 22”) is resolved.

Suggested sequencing

  1. nx migrate nx@23 first, run migrations, commit (use NX_MIGRATE_SKIP_INSTALL / legacy-peer-deps only if pnpm peer resolution complains).
  2. nx migrate @angular/core@22 @angular/cli@22 (+ devkit/schematics/ng-packagr), run migrations.
  3. Bump angular-eslint 22 + eslint 10 together; re-run lint.
  4. Bump typescript 6 — watch the TS6 baseUrl deprecation interaction with Nx's nxViteTsPaths (noted in nrwl/nx#35851); keep relative ./ paths or apply the migration.
  5. Verify keycloak-angular 22 peer; bump if compatible.
  6. Full pnpm test-all + nx build + e2e before merge.

Doing the low-risk roll-ups (#229/#230) first will shrink the diff/noise when this epic lands.

## Framework major upgrade — coupled dependency set + unblock note While triaging `package.json` for outdated libs, I split the **safe / non-framework** upgrades into their own tickets (#229 #230 #231 #232 #233 #234). Everything below stays here because it's part of the **one coupled Angular/Nx jump** and must move together: | Package(s) | Current | Target | | --- | --- | --- | | `@angular/*` (core, common, compiler(-cli), forms, router, animations, elements, material, cdk, aria, google-maps, platform-*, service-worker, ssr, language-service) | 21.2.x | 22.0.1 | | `@angular-devkit/*`, `@schematics/angular`, `@angular/cli`, `@angular/pwa` | 21.2.11 | 22.0.1 | | `ng-packagr` | 21.2.3 | 22.0.0 | | `@angular-eslint/*` + `angular-eslint` | 21.4.0 | 22.0.0 | | `@nx/*` + `nx` | 22.7.2 | 23.0.0 | | `eslint` | 9.39.3 | 10.5.0 (needs angular-eslint 22) | | `typescript` | 5.9.3 | 6.0.3 (Angular 22 supports TS 6) | | `keycloak-angular` | 21.0.0 | 22.0.0 (verify Angular peer) | ### Unblock note (the premise changed) **Nx 23.0.0 was released 2026-06-16 and adds Angular 22 support.** Per the [Nx ↔ Angular version matrix](https://nx.dev/docs/technologies/angular/guides/angular-nx-version-matrix), Angular 22 pairs with Nx 23 (latest). So the earlier blocker (“Nx latest doesn't support Angular 22”) is resolved. ### Suggested sequencing 1. `nx migrate nx@23` first, run migrations, commit (use `NX_MIGRATE_SKIP_INSTALL` / legacy-peer-deps only if pnpm peer resolution complains). 2. `nx migrate @angular/core@22 @angular/cli@22` (+ devkit/schematics/ng-packagr), run migrations. 3. Bump `angular-eslint` 22 + `eslint` 10 together; re-run lint. 4. Bump `typescript` 6 — watch the **TS6 `baseUrl` deprecation** interaction with Nx's `nxViteTsPaths` (noted in nrwl/nx#35851); keep relative `./` paths or apply the migration. 5. Verify `keycloak-angular` 22 peer; bump if compatible. 6. Full `pnpm test-all` + `nx build` + e2e before merge. Doing the low-risk roll-ups (#229/#230) first will shrink the diff/noise when this epic lands.
Author
Owner

Folding in #233: @fortawesome/angular-fontawesome 4 → 5 is blocked here — v5.0.0 requires @angular/core ^22.0.0. Bundle it with the Angular 22 upgrade. Usage is minimal (single component classes.component.ts), so it should be a quick add once Angular 22 lands.

Folding in #233: `@fortawesome/angular-fontawesome 4 → 5` is blocked here — v5.0.0 requires `@angular/core ^22.0.0`. Bundle it with the Angular 22 upgrade. Usage is minimal (single component `classes.component.ts`), so it should be a quick add once Angular 22 lands.
Author
Owner

Re-verification (2026-06-17): still BLOCKED — correcting the earlier unblock note

The 2026-06-17 comment claimed Nx 23 unblocked Angular 22. Re-checking the live peer ranges today, that's not actually true at the dependency level:

  • @nx/angular@23.0.0 (latest) still caps the Angular build tooling below 22:
    • @angular/build: >= 19.0.0 < 22.0.0
    • ng-packagr: >= 19.0.0 < 22.0.0
  • Checked latest (23.0.0), next (23.0.0-rc.4), and canarynone lift the cap. So nx migrate will again bump only the Angular runtime packages and hold @angular/build/ng-packagr/devkit at 21.2.x. Same blocker as the original 2026-06-08 finding.

Decision: remain on hold. Re-check @nx/angular periodically; proceed once a release allows @angular/build@22.

Third-party Angular-peer libs — verified compatibility (for when we resume)

Ready to bump with the epic:

Lib Target Angular peer
keycloak-angular 22.0.0 ^22
@fortawesome/angular-fontawesome (folds in #233) 5.0.0 ^22
@fullcalendar/angular 6.1.21 12 - 22
ngx-socket-io 4.11.0 (current) already ^22
ngx-image-cropper 9.1.6 (current) >=17.3 (open)

Also still capped <22 (no v22 release yet — will need peerDependencyRules.allowedVersions overrides + functional verification):

Lib Latest Angular peer Usage
@storybook/angular 10.4.6 (next 10.5.0-alpha.7) >=18 <22 dev-only (not in deploy path)
rete-angular-plugin 2.6.0 >=12 <22 dev-tools-diagram
ng-qrcode 21.0.0 >=21 <22 dev-tools-qr-code, fundraiser receipt
ngx-mask 21.0.1 ^21 main.ts provider + marks-customer

Sequenced plan (when unblocked)

Phase 0 — feasibility spike (throwaway branch): nx migrate latest, inspect migrations.json; if @angular/build/ng-packagr are still capped, force them to 22 via pnpm.overrides/peerDependencyRules; smoke-test nx build spikersoft --configuration production + nx test spikersoft (vitest @angular/build:unit-test runner + the jsdom Storage shim). Decision gate: green → proceed; else hold. Discard the spike.

Phase 1 — framework migration (single coordinated branch):

  1. nx migrate nx@23 → run migrations → commit.
  2. nx migrate @angular/core@22 @angular/cli@22 (+ devkit/schematics/ng-packagr/material/cdk) → run codemods → install.
  3. angular-eslint@22 + eslint@10 together; fix new lint violations.
  4. typescript@6 — watch the TS6 baseUrl/paths + Nx nxViteTsPaths interaction (tsconfig.base currently uses moduleResolution: "bundler", baseUrl: "./" + ~70 path maps).

Phase 2 — third-party libs: bump the ready set; add peer overrides for the 4 still-capped libs and functionally verify each (QR render, input masking, rete diagram, Storybook build).

Phase 3 — validation: pnpm test-all (40 projects), prod nx build, pnpm e2e, lint + styles. Ship as one PR (the migration is atomic; splitting leaves the workspace uninstallable mid-way).

Scope: ~70 Nx libraries + app (incl. SSR) + Storybook + e2e. No production runtime risk during dev (prod is the static nginx image).

## Re-verification (2026-06-17): still BLOCKED — correcting the earlier unblock note The 2026-06-17 comment claimed Nx 23 unblocked Angular 22. Re-checking the **live peer ranges** today, that's not actually true at the dependency level: - **`@nx/angular@23.0.0` (latest) still caps the Angular build tooling below 22:** - `@angular/build`: `>= 19.0.0 < 22.0.0` - `ng-packagr`: `>= 19.0.0 < 22.0.0` - Checked `latest` (23.0.0), `next` (23.0.0-rc.4), and `canary` — **none** lift the cap. So `nx migrate` will again bump only the Angular *runtime* packages and hold `@angular/build`/`ng-packagr`/devkit at 21.2.x. Same blocker as the original 2026-06-08 finding. **Decision: remain on hold.** Re-check `@nx/angular` periodically; proceed once a release allows `@angular/build@22`. ## Third-party Angular-peer libs — verified compatibility (for when we resume) **Ready to bump with the epic:** | Lib | Target | Angular peer | | --- | --- | --- | | `keycloak-angular` | 22.0.0 | `^22` | | `@fortawesome/angular-fontawesome` (folds in #233) | 5.0.0 | `^22` | | `@fullcalendar/angular` | 6.1.21 | `12 - 22` | | `ngx-socket-io` | 4.11.0 (current) | already `^22` | | `ngx-image-cropper` | 9.1.6 (current) | `>=17.3` (open) | **Also still capped `<22` (no v22 release yet — will need `peerDependencyRules.allowedVersions` overrides + functional verification):** | Lib | Latest | Angular peer | Usage | | --- | --- | --- | --- | | `@storybook/angular` | 10.4.6 (next 10.5.0-alpha.7) | `>=18 <22` | dev-only (not in deploy path) | | `rete-angular-plugin` | 2.6.0 | `>=12 <22` | `dev-tools-diagram` | | `ng-qrcode` | 21.0.0 | `>=21 <22` | `dev-tools-qr-code`, fundraiser receipt | | `ngx-mask` | 21.0.1 | `^21` | `main.ts` provider + `marks-customer` | ## Sequenced plan (when unblocked) **Phase 0 — feasibility spike (throwaway branch):** `nx migrate latest`, inspect `migrations.json`; if `@angular/build`/`ng-packagr` are still capped, force them to 22 via `pnpm.overrides`/`peerDependencyRules`; smoke-test `nx build spikersoft --configuration production` + `nx test spikersoft` (vitest `@angular/build:unit-test` runner + the jsdom Storage shim). Decision gate: green → proceed; else hold. Discard the spike. **Phase 1 — framework migration (single coordinated branch):** 1. `nx migrate nx@23` → run migrations → commit. 2. `nx migrate @angular/core@22 @angular/cli@22` (+ devkit/schematics/ng-packagr/material/cdk) → run codemods → install. 3. `angular-eslint`@22 + `eslint`@10 together; fix new lint violations. 4. `typescript`@6 — watch the TS6 `baseUrl`/`paths` + Nx `nxViteTsPaths` interaction (tsconfig.base currently uses `moduleResolution: "bundler"`, `baseUrl: "./"` + ~70 path maps). **Phase 2 — third-party libs:** bump the ready set; add peer overrides for the 4 still-capped libs and functionally verify each (QR render, input masking, rete diagram, Storybook build). **Phase 3 — validation:** `pnpm test-all` (40 projects), prod `nx build`, `pnpm e2e`, lint + styles. Ship as **one PR** (the migration is atomic; splitting leaves the workspace uninstallable mid-way). **Scope:** ~70 Nx libraries + app (incl. SSR) + Storybook + e2e. No production runtime risk during dev (prod is the static nginx image).
Author
Owner

Done in the 2026-07-16 spikersoft-angular deps pass — PRs #204–#211, landing as batch 6 (PR #211): Angular 22.0.6, Nx 23, TypeScript 6, ESLint 10 (plus ng-packagr 22 and the batch 1–5 groundwork). Master is green on the new toolchain (build, test-and-lint, both e2e walks). Known follow-ups are tracked separately (e.g. #236 for the @types/google.maps unpin; the rete-angular-plugin Angular-22 fallout was #622, fixed in PR #214). Closing.

Done in the 2026-07-16 spikersoft-angular deps pass — PRs #204–#211, landing as batch 6 (PR #211): Angular 22.0.6, Nx 23, TypeScript 6, ESLint 10 (plus ng-packagr 22 and the batch 1–5 groundwork). Master is green on the new toolchain (build, test-and-lint, both e2e walks). Known follow-ups are tracked separately (e.g. #236 for the @types/google.maps unpin; the rete-angular-plugin Angular-22 fallout was #622, fixed in PR #214). Closing.
Sign in to join this conversation.