technologynews
Angular 22 — mi az újdonság, és mi marad a Signal-korszakból
Stack:
Mit tanulsz
- angularBevezető
Mit tanulsz meg ebből a cikkből?
Az Angular 22 nem forradalmi release — a v18 óta épülő signal-alapú stack ér be. Ebben a cikkben végigmegyünk a zoneless default-on, a stable Signal Forms és
resource() API-n, a szigorodó template type checkeren, a Vite/Rspack build pipeline-on, az incremental hydration stable státuszán, és a v21 → v22 migráció napi részletein.01 — Áttekintés
A stabilizáció kora
A v16 óta tartó Signal-forradalom az Angular 22-ben ér be. A reactive primitíveket már v17-ben megkaptuk, a signal-alapú inputokat v17.1-ben, a
resource()-ot v19-ben kísérleti jelleggel, a zoneless módot v18-ban opcionálisan. A v22 fő üzenete: ami eddig kísérlet volt, az most alapértelmezett.Release-ciklus — 6 hónap, 2 major/év
Az Angular továbbra is félévente ad ki egy major verziót. Az LTS 18 hónapig él, így az Angular 19 a v22 megjelenésekor még támogatott — de új funkciót már nem kap, csak biztonsági javítást.
Mit tanulsz
- zonelessKözéphaladó
02 — Zoneless default
Vége a zone.js korszakának
Az
ng new alapból provideZonelessChangeDetection()-t generál. A zone.js kikerült a polyfills-ből, az NgZone pedig háttérbe szorul — csak régi kódokhoz marad meg. Cserébe kisebb a bundle (~40 KB), gyorsabb a first paint, és a change detection is kiszámíthatóbb.main.tstypescript
// Angular 22 — generated by `ng new`
import { bootstrapApplication } from '@angular/platform-browser';
import { provideZonelessChangeDetection } from '@angular/core';
bootstrapApplication(AppComponent, {
providers: [
provideZonelessChangeDetection(),
provideRouter(routes),
// ...
]
});
// What triggers CD now?
// - Signal writes (computed graph invalidation)
// - afterNextRender / afterRender
// - Explicit ChangeDetectorRef.markForCheck() (rare)
// - Template event bindings (auto-flushes)Ami nem fog magától működni
A közvetlen
setTimeout, setInterval, addEventListener hívások zoneless módban nem indítanak change detection-t. A régi kódot vagy átírod signal()-re, vagy NgZone.run(...)-nel kényszeríted ki a frissítést. A HttpClient válaszok viszont továbbra is triggerelik a CD-t — azokkal nincs dolgod.Mit tanulsz
- signal-formsKözéphaladó
03 — Signal Forms
A ReactiveForms utódja — stable
A Signal Forms v20-ban érkezett kísérletiként, v21-ben RC-ként, v22-ben pedig stable. A lényeg: minden mezőérték, státusz és hiba egy-egy signal. Nincs
valueChanges.subscribe(), nincs takeUntilDestroyed() boilerplate — a reactive graph magától elintézi.booking-form.component.tstypescript
import { form, field, validators } from '@angular/forms/signals';
interface BookingFormValue {
name: string;
email: string;
nights: number;
}
@Component({
template: `
<form (submit)="submit()">
<input [field]="f.name" />
@if (f.name.invalid() && f.name.touched()) {
<span class="err">{{ f.name.errors()[0]?.message }}</span>
}
<input [field]="f.email" />
<input type="number" [field]="f.nights" />
<button [disabled]="f.invalid() || f.pending()">
{{ f.pending() ? 'Submitting...' : 'Submit' }}
</button>
</form>
`
})
export class BookingFormComponent {
readonly f = form<BookingFormValue>({
name: field('', validators.required),
email: field('', validators.required, validators.email),
nights: field(1, validators.min(1), validators.max(30))
});
readonly summary = computed(() =>
`${this.f.name.value()} — ${this.f.nights.value()} nights`
);
submit() {
if (this.f.invalid()) return;
this.api.create(this.f.value());
}
}- Típusbiztos mezőkezelés — az
f.emailtudja, hogystring, nemany. - Async validátor közvetlenül signalból:
validators.async(checkEmailUnique). - Automatikus cleanup — nincs
takeUntilDestroyed, a komponens megszűnésekor az effektek maguktól leállnak. - Derived state — a
computed()valós időben követi a forrást.
Mit tanulsz
- resource-apiKözéphaladó
04 — resource() stable
Aszinkron adatbetöltés — signalban
A
resource() v22-ben lett stable. Ez a signal-alapú alternatíva a toSignal(httpClient.get(...)) pattern-re — csak sokkal többet tud: automatikus reload(), állapotgép (idle | loading | resolved | error), új trigger esetén megszakítás, és rxResource variáns RxJS stream-hez.project-list.component.tstypescript
import { Component, signal, resource } from '@angular/core';
@Component({
template: `
@switch (projects.status()) {
@case ('loading') { <p-skeleton /> }
@case ('error') { <div class="err">{{ projects.error() }}</div> }
@case ('resolved') {
@for (p of projects.value(); track p.id) {
<app-project-card [project]="p" />
}
}
}
<select [(ngModel)]="filter">
<option value="all">All</option>
<option value="active">Active</option>
</select>
`
})
export class ProjectListComponent {
readonly filter = signal<'all' | 'active'>('all');
readonly projects = resource({
request: () => ({ filter: this.filter() }),
loader: async ({ request, abortSignal }) => {
const res = await fetch(`/api/projects?f=${request.filter}`, {
signal: abortSignal
});
if (!res.ok) throw new Error('Failed to load');
return res.json();
}
});
reload() {
this.projects.reload();
}
}Automatikus abort
Ha a
filter signal 200ms-en belül kétszer változik, a resource() az első kérést AbortController-rel leállítja — nincs szükség kézzel írt switchMap-re vagy takeUntil-re. Csak átadod az abortSignal-t a loader-nek.Mit tanulsz
- angularKözéphaladó
05 — Template DX
Szigorúbb type check, okosabb LSP
strictTemplates: trueaz alapértelmezett új projektben. A compiler az@if,@for,@switchblokkokon belül is követi a típus-szűkítést.- Signal auto-tracking a templateben — ha signalt olvasol a
{{ }}között, az LSP szól, ha lefelejtetted a()-t. - Host bindings signallal — az
@HostBindinghelyett ahost: { 'class.active': isActive }szintaxis, ahol azisActivelehet signal. - Deferred loading diagnostika — a
@defertriggerek (viewport, interaction, timer) az IDE-ben is láthatók.
Mit tanulsz
- angularKözéphaladó
06 — Build & DX
Vite mindenhol, esbuild éles, Rspack kísérleti
A Vite-alapú dev szerver v17 óta egyre gyorsabb — v22-ben a HMR átlaga 30ms alá esik, még 200+ komponenses app-oknál is. A production build alapból esbuild-et használ, és v22-ben egy kísérleti Rspack adapter is érkezik. A Rust-alapú bundler nagyobb NX workspace-eken már érezhetően gyorsabb.
angular.jsonjson
// angular.json — opt-in Rspack (experimental in v22)
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"bundler": "rspack", // <-- experimental
"outputPath": "dist/app",
"browser": "src/main.ts"
}
}
}Mit tanulsz
- incremental-hydrationKözéphaladó
07 — SSR & hidratáció
Incremental hydration — stable
A v19-ben érkezett incremental hydration v22-ben lett stable. A
@defer (hydrate on viewport) azt jelenti, hogy a fold feletti rész azonnal interaktív, a fold alatti komponensek pedig csak akkor hidrálnak, amikor láthatóvá válnak. A site app Core Web Vitals számaiban ezzel tudtuk kipipálni a TBT-t — valódi javulás.blog-post.page.tstypescript
@Component({
template: `
<app-hero />
<app-primary-nav />
@defer (hydrate on viewport) {
<app-comments-section />
}
@defer (hydrate on interaction) {
<app-heavy-chart />
}
@defer (hydrate on idle) {
<app-newsletter />
}
`
})
export class BlogPostPage {}Mit tanulsz
- angularKözéphaladó
08 — Migráció
v21 → v22 — mit vár tőled
ng update @angular/core @angular/cli— a schematics a legtöbbet automatikusan elintézi.- Zone.js opcionálisan maradhat: ha az app még nem áll készen a zoneless átállásra, kézzel add hozzá a
provideZoneChangeDetection()-t. - ReactiveForms és Signal Forms megfér egymás mellett — nem kell mindent egyben átírni, de az új kódot már érdemes Signal Forms-ban írni.
toSignal(http.get(...))→resource({ loader: () => http.get(...) })— ha abort + reload hasznos.- TypeScript 5.9+ szükséges — a template type checker használja a
satisfies-t és aconsttípusparamétereket.
Breaking change-ek szintje: alacsony
Az Angular 22 inkrementális kiadás — a legtöbb v21-es app egyetlen
ng update-tel átáll. A nagy fájdalom a v16→v17 vagy v14→v15 váltásnál volt, most ez nem jön vissza. Az Angular csapat következetesen a „stabilize, don't destabilize” elvet követi.09 — Konklúzió
Érdemes frissíteni?
Igen — de nem a csillivilli új feature miatt, hanem mert a stabil alapok mostantól default-ok. A zoneless, a signal forms és a resource mind „ajánlott” státuszba ért. Aki v22-n indít új appot, három évig nem szembesül deprecation-nel — ez a legnagyobb ajándék ebben a kiadásban.
A jó framework akkor érik be, amikor már nem kell tovább izgulnod érte.