← Vissza a cikkekhez
technologynews

Angular 22 — mi az újdonság, és mi marad a Signal-korszakból

Zsaga
#featured#angular#angular-22#signals#zoneless#signal-forms#resource#hydration#vite#rspack
Angular 22 kulcsfejlesztések — zoneless default, signal forms, resource API, Vite DX
Az Angular 22 főbb területei — inkrementális, de jelentős változások
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.email tudja, hogy string, nem any.
  • 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: true az alapértelmezett új projektben. A compiler az @if, @for, @switch blokkokon 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 @HostBinding helyett a host: { 'class.active': isActive } szintaxis, ahol az isActive lehet signal.
  • Deferred loading diagnostika — a @defer triggerek (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

  1. ng update @angular/core @angular/cli — a schematics a legtöbbet automatikusan elintézi.
  2. 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.
  3. 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.
  4. toSignal(http.get(...))resource({ loader: () => http.get(...) }) — ha abort + reload hasznos.
  5. TypeScript 5.9+ szükséges — a template type checker használja a satisfies-t és a const tí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.

Vissza az elejére