---
title: "Angular 22: What Actually Changed, and What to Do in a Production App"
description: "A senior, production-first guide to Angular 22: the OnPush default, the stabilized Signal Forms and async-signal APIs, the testing migrations, the smaller default flips that bite on upgrade, and a deliberate plan for adopting it."
deck: "Angular 22 shipped on [June 3, 2026](https://angular.dev/events/v22). It is mostly a graduation release: Signal Forms, the `resource` and `httpResource` async APIs, and Angular Aria all left experimental and are now stable. But one default flip touches every component you own: OnPush is now the change detection default. Here is what changed, and what I would actually do about it."
author: "André Ramos"
url: "https://andreramos.dev/angular/angular-22-what-changed/"
lang: "en"
type: "article"
---

# Angular 22: What Actually Changed, and What to Do in a Production App

> Angular 22 shipped on [June 3, 2026](https://angular.dev/events/v22). It is mostly a graduation release: Signal Forms, the `resource` and `httpResource` async APIs, and Angular Aria all left experimental and are now stable. But one default flip touches every component you own: OnPush is now the change detection default. Here is what changed, and what I would actually do about it.

## What Angular 22 actually is

Angular 22 landed on June 3, 2026. Read the headline feature list and it looks enormous. Read it as a tech lead with an app in production and it sorts into two piles: experiments that graduated, and defaults that flipped.

The graduations are opt-in. Signal Forms, the `resource` and `httpResource` async APIs, and Angular Aria are now stable, but nothing forces you to adopt them. The default flips are not opt-in. OnPush change detection, `strictTemplates`, the Fetch HTTP backend, and incremental hydration now apply unless you say otherwise, and `ng update` writes migrations into your code to preserve the old behavior.

So the real upgrade question is not "what is new." It is "which migrations did the CLI just write into my app, and which of them do I actually want to keep." The rest of this guide is that question, area by area.

## The change that touches every component: OnPush by default

The headline for an existing app is one line in the changelog: the default change detection strategy is now OnPush. A component that never set `changeDetection` used to run eager, checking on every tick. In v22 that same component is OnPush.

`ng update` does not leave you exposed. It writes `changeDetection: ChangeDetectionStrategy.Eager` onto your existing components so their behavior does not change. That is the safe move, and it is also a to-do list: each added `Eager` line is a component that was relying on eager checking, and a candidate to make properly OnPush over time.

What I would do: let new components be OnPush, because the new default is the right one, and treat the migration's `Eager` additions as a backlog, not a conclusion. The components that break when you remove `Eager` are the ones mutating template state without telling Angular, the same class of code that surfaces when an app goes [zoneless](/angular/code-that-breaks-when-angular-goes-zoneless). v22 just made the question unavoidable.

*The new default, and what the migration writes on old code*

```ts
// v22: this component is OnPush by default now. No strategy line needed.
@Component({ selector: 'app-badge', template: '{{ count() }}' })
export class BadgeComponent {
  count = signal(0);   // signal writes mark the OnPush view dirty, so this is fine
}

// What ng update adds to your OLD components to preserve eager behavior:
@Component({
  selector: 'app-legacy',
  changeDetection: ChangeDetectionStrategy.Eager,   // added by the migration
  template: '...',
})
export class LegacyComponent {}
```

## The graduations: what is stable now, and whether to adopt

Three things left experimental in v22, and the honest answer to "should I adopt" is different for each.

Signal Forms are the big one. They were a developer preview in v21, and stable changes the calculus: new code can use them, and v22 filled the gaps that made me cautious before (date validators, debounced async validation, `getError` with type narrowing). I walk through [how I would adopt them now](/angular/signal-forms-not-my-default-yet), and the short version is: reach for them on a new form, do not rewrite working reactive forms for it.

The `resource` and `httpResource` APIs are the async-signals data layer, and they are stable too. That settles the cautious framing in [HTTP state without turning everything into Signals](/angular/http-state-without-signals-everywhere): `httpResource` is no longer an experiment to isolate, it is a tool you can put on a real read. Angular Aria graduated to general availability alongside them, and now works with Signal Forms, which makes accessible custom form controls less of a build-it-yourself job.

| Feature | v21 status | v22 status | What I would do |
|---|---|---|---|
| Signal Forms | Developer preview | Stable | Use for new forms; do not rewrite working reactive forms |
| `resource` / `httpResource` | Experimental | Stable | Use for new remote reads; keep RxJS where streams compose |
| Angular Aria (`@angular/aria`) | Developer preview | Stable (GA) | Adopt for accessible custom controls |

## Testing moved too, mostly in your favor

If you migrated tests to Vitest, v22 turned two workarounds into supported features. The `zone.js/plugins/vitest-patch` that keeps `fakeAsync` alive is now the documented path, not a trick. And there are new schematics: a `migrate-karma-to-vitest` migration does the runner switch, and `refactor-jasmine-vitest` gained a `--fake-async` flag that rewrites timing tests to native Vitest timers for you.

That does not retire the work, it reshapes it. The schematic converts the mechanical cases, but the [Promise-in-the-chain tests still need review](/angular/angular-vitest-async-validator-pending), and you still have to decide [whether to migrate a suite at all](/angular/move-angular-test-suite-to-vitest). The floor is higher than it was a release ago.

*The v22 testing schematics*

```bash
# Convert Jasmine specs to Vitest, with native timers for fakeAsync tests:
ng generate @schematics/angular:refactor-jasmine-vitest --fake-async --include=src/app
```

## The smaller defaults that bite on upgrade

A handful of quieter flips show up as surprises if you do not know them. The HttpClient now uses the Fetch backend by default and `withFetch()` is deprecated, with the migration removing it. `strictTemplates` is on by default, so templates that type-checked loosely may start failing the build. Incremental hydration is the default for SSR apps. And the toolchain moved: TypeScript 6 is required, Node 20 is out and Node 26 is in.

None of these is hard, but each is a place where a clean `ng update` still leaves you a manual decision. The router has one with no migration at all: `paramsInheritanceStrategy` now defaults to `'always'`, which can change what a child route reads from its params.

## What I would do this week

The upgrade itself is `ng update @angular/core @angular/cli`, and then the real work is reading what it wrote. Run the migrations, then review the diff with two questions: which `Eager` change-detection additions do I want to keep, and which deprecation removals am I comfortable with.

After the mechanical upgrade, the adoption decisions are the interesting part, and they are the same disciplined filter as always: [adopt what is safe, spike what is not, leave stable code alone](/angular/adopt-spike-wait-angular-21). Signal Forms and `httpResource` being stable moves them from the spike column to the adopt-for-new-code column, which is exactly the kind of change [a modernization plan](/angular/angular-30-day-modernization-plan) should absorb without becoming a rewrite.

v22 rewards teams that were already drifting toward signals, and the OnPush default quietly raises the bar on change-detection hygiene for everyone else. It is a good release to be deliberate about.

## Reusable artifact: Angular 22 upgrade checklist

- Run `ng update @angular/core @angular/cli` and let the schematics apply their migrations.
- Confirm the toolchain: TypeScript 6, Node 22.22+, 24, or 26 (Node 20 is dropped).
- Review every `changeDetection: Eager` the migration added: each is an OnPush candidate, not a conclusion.
- Decide on the Fetch backend (`withFetch()` is removed) and on the `strictTemplates` failures the build now surfaces.
- Note the router default: `paramsInheritanceStrategy` is now `'always'` with no migration provided.
- Treat Signal Forms and `httpResource` as adopt-for-new-code now that they are stable; do not rewrite working code for it.

## FAQ

### When was Angular 22 released, and what does it require?

Angular 22 was released on June 3, 2026. It requires TypeScript 6 and Node 22.22+, 24, or 26; Node 20 support was dropped. RxJS 7.4+ is still supported.

### What is the biggest change in Angular 22 for an existing app?

The default change detection strategy is now OnPush. A component without an explicit `changeDetection` strategy is OnPush in v22. `ng update` preserves old behavior by adding `ChangeDetectionStrategy.Eager` to your existing components, but new components are OnPush by default.

### Are Signal Forms stable in Angular 22?

Yes. Signal Forms graduated from developer preview to stable in v22, along with the `resource` and `httpResource` async-signal APIs and the `@angular/aria` package. They are production-ready, though adopting them is still optional.

### Did Angular 22 change anything about Vitest testing?

Yes, in your favor. The `zone.js/plugins/vitest-patch` that keeps `fakeAsync` working is now the documented path, and v22 adds a `migrate-karma-to-vitest` schematic plus a `--fake-async` flag on `refactor-jasmine-vitest` that rewrites timing tests to native Vitest timers.

### Is upgrading to Angular 22 risky?

The mechanical part is an `ng update` with automatic migrations. The decisions are reviewing the `Eager` change-detection additions and the deprecation removals like `withFetch()`. Nothing forces you to adopt the newly stable APIs, so the risk is mostly in what you choose to change after the upgrade, not the upgrade itself.

## Sources checked

- https://angular.dev/events/v22
- https://angular.dev/reference/versions
- https://angular.dev/guide/forms/signals/overview
- https://angular.dev/guide/signals/resource
- https://angular.dev/guide/zoneless
- https://angular.dev/guide/testing/migrating-to-vitest
- https://blog.ninja-squad.com/2026/06/03/what-is-new-angular-22.0

## Related

- [What to Adopt, Spike, or Wait On in Angular 21](https://andreramos.dev/angular/adopt-spike-wait-angular-21/)
- [How I Would Adopt Signal Forms Now That They Are Stable in Angular 22](https://andreramos.dev/angular/signal-forms-not-my-default-yet/)
- [When to Move an Angular Test Suite to Vitest](https://andreramos.dev/angular/move-angular-test-suite-to-vitest/)
