Modern Angular
Angular 22: What Actually Changed, and What to Do in a Production App
Angular 22 shipped on June 3, 2026. 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. v22 just made the question unavoidable.
// 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, 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: 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, and you still have to decide whether to migrate a suite at all. The floor is higher than it was a release ago.
# Convert Jasmine specs to Vitest, with native timers for fakeAsync tests:
ng generate @schematics/angular:refactor-jasmine-vitest --fake-async --include=src/appThe 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. 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 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/cliand let the schematics apply their migrations. - Confirm the toolchain: TypeScript 6, Node 22.22+, 24, or 26 (Node 20 is dropped).
- Review every
changeDetection: Eagerthe migration added: each is an OnPush candidate, not a conclusion. - Decide on the Fetch backend (
withFetch()is removed) and on thestrictTemplatesfailures the build now surfaces. - Note the router default:
paramsInheritanceStrategyis now'always'with no migration provided. - Treat Signal Forms and
httpResourceas 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
Modern Angular Playbook
This article is one play.
The Modern Angular Playbook collects the diagnostic, the adoption matrix, eleven plays, and the 30-day plan. Free, in English and Portuguese.
You get both PDFs by email, through the Dojo IA list.
André Ramosavailable for remote roles, UTC−3Get in touch →