AngularAtlasAusg. 22.2

Kap. 15Echtzeit & offline67 / 75

Offline-first: Service Worker & Caching

Der Angular Service Worker: Caching-Strategien, Update-Hinweise und ein Postausgang für Änderungen, die offline entstehen.

stabil ~0 Min. Lesezeit Offizielle Doku

Eine Web-App braucht normalerweise für alles das Netzwerk, sogar um sich selbst anzuzeigen. Ein Service Worker sitzt zwischen App und Netzwerk: Er kann aus einem Cache antworten, das Netzwerk mit Zeitlimit versuchen oder beides. Gut gemacht öffnet sich die App im langsamen Zug sofort und läuft im Tunnel weiter.

Angular hat einen eigenen Service Worker, gesteuert über eine Konfigurationsdatei statt über Code. Diese Seite behandelt beide Hälften: Lesen (was du zeigst, wenn das Netzwerk langsam ist oder fehlt) und Schreiben (was du mit den offline gemachten Änderungen tust).

Warum das wichtig ist
Offline ist kein Ausnahmefall: Aufzüge, Züge, Hotel-WLAN, ein Balken Empfang. Und ein langsames Netzwerk ist schlimmer als keins: Die Anfrage scheitert nicht, sie hängt nur. Ein Timeout, der auf den Cache zurückfällt, macht aus einem 30-Sekunden-Spinner eine Antwort in drei.

Einschalten

ng add @angular/pwa fügt das Paket @angular/service-worker, ein Manifest, Icons, eine ngsw-config.json und provideServiceWorker() hinzu. Der Worker läuft nur in Production-Builds und über HTTPS (localhost ist die Ausnahme). registerWhenStable:30000 registriert ihn, sobald die App stabil ist, spätestens nach 30 Sekunden, damit seine Downloads nicht mit dem ersten Rendern konkurrieren.

ng add @angular/pwa
# fügt @angular/service-worker, ngsw-config.json, ein Manifest, Icons und provideServiceWorker() hinzu
ng build   # der Worker läuft nur in Production-Builds, über HTTPS (oder auf localhost)

Was gecacht wird: assetGroups und dataGroups

assetGroups cachen die eigenen Dateien der App. prefetch lädt bei der Installation alles herunter — die Shell: index.html, JS, CSS —, damit die App offline startet. lazy cacht eine Datei erst, wenn sie zum ersten Mal angefragt wird: Bilder, Fonts, selten genutzte Seiten. Dateien mit Hash im Namen veralten nie; der Worker prüft bei jeder Navigation, ob es eine neue Version gibt.

dataGroups cachen Antworten deiner API, mit einer von zwei Strategien. freshness fragt zuerst das Netzwerk und fällt auf den Cache zurück, wenn das Netzwerk ausfällt oder langsamer als timeout ist: richtig für Daten, die sich ändern (Preise, Bestand, Benachrichtigungen). performance antwortet zuerst aus dem Cache und geht nur ins Netzwerk, wenn es keine Kopie gibt; mit refreshAhead wird eine Kopie, die so nah an maxAge kommt, weiterhin angezeigt, aber vor dem Ablauf im Hintergrund aktualisiert: richtig für Daten, die sich selten ändern (ein Katalog, Einstellungen, Übersetzungen).

{
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app-shell",
      "installMode": "prefetch",
      "resources": { "files": ["/favicon.ico", "/index.html", "/*.css", "/*.js"] }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": { "files": ["/assets/**", "/*.(svg|png|webp|woff2)"] }
    }
  ],
  "dataGroups": [
    {
      "name": "prices",
      "urls": ["/api/prices/**"],
      "cacheConfig": { "strategy": "freshness", "timeout": "3s", "maxSize": 50, "maxAge": "1h" }
    },
    {
      "name": "catalogue",
      "urls": ["/api/products/**"],
      "cacheConfig": {
        "strategy": "performance",
        "maxSize": 200,
        "maxAge": "7d",
        "refreshAhead": "1d"
      }
    }
  ]
}
LiveDieselbe Anfrage: drei Strategien, drei Netzwerke
Strategie
Netzwerk
Im Cache
  1. 0 ms Anfrage ans Netzwerk gesendet
  2. 3000 ms Timeout nach 3 s → aus dem Cache beantwortet
  3. 6000 ms das Netzwerk antwortet spät: der Cache wird fürs nächste Mal aktualisiert
Inhalt nach
3000 ms
Quelle
Cache
Alter der Daten
10 Minuten
Wähle ein langsames Netzwerk: Ohne Worker wartest du sechs Sekunden, mit freshness drei, mit performance ein paar Millisekunden. Geh dann mit leerem Cache offline.

Achte auf maxAge: Es ist eine harte Grenze, kein Hinweis. Ältere Einträge werden verworfen, auch ohne Netzwerk — eine abgelaufene Kopie wird nie angezeigt, offline oder nicht. Wähle es nach den ältesten Daten, die du noch zeigen würdest.

Neue Versionen: fragen, nicht den Code unter den Füßen des Nutzers tauschen

Nach einem Deploy bemerkt der Worker das bei der nächsten Navigation und lädt die neue Version im Hintergrund. Der offene Tab läuft mit der alten weiter — zwei Versionen zu mischen ist das, was Apps kaputt macht. SwUpdate.versionUpdates sendet VERSION_READY, wenn die neue Version vollständig ist; zeig eine Meldung und lade neu, wenn der Nutzer zustimmt. unrecoverable heißt, die Dateien der laufenden Version liegen nicht mehr auf dem Server: neu laden. Ein Tab, der tagelang offen bleibt, sollte außerdem ab und zu checkForUpdate() aufrufen.

import { ApplicationRef, Component, DestroyRef, inject, signal } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { SwUpdate, type VersionReadyEvent } from '@angular/service-worker';
import { filter, interval } from 'rxjs';

@Component({
  selector: 'app-update-banner',
  template: `
    @if (ready()) {
      <div role="status">
        Eine neue Version ist bereit.
        <button type="button" (click)="reload()">Neu laden</button>
      </div>
    }
  `,
})
export class UpdateBanner {
  private readonly updates = inject(SwUpdate);
  protected readonly ready = signal(false);

  constructor() {
    if (!this.updates.isEnabled) return; // Dev-Modus oder ein Browser ohne Service Worker
    const destroyRef = inject(DestroyRef);

    this.updates.versionUpdates
      .pipe(
        filter((e): e is VersionReadyEvent => e.type === 'VERSION_READY'),
        takeUntilDestroyed(destroyRef),
      )
      .subscribe(() => this.ready.set(true)); // fragen; nicht mitten in einem Formular neu laden

    // die Dateien der laufenden Version sind vom Server verschwunden: nur ein Reload hilft
    this.updates.unrecoverable
      .pipe(takeUntilDestroyed(destroyRef))
      .subscribe(() => document.location.reload());

    // ein Tab, der tagelang offen bleibt, muss auch ab und zu nachsehen
    const appRef = inject(ApplicationRef);
    void appRef.whenStable().then(() =>
      interval(6 * 60 * 60 * 1000)
        .pipe(takeUntilDestroyed(destroyRef))
        .subscribe(() => void this.updates.checkForUpdate()),
    );
  }

  protected reload(): void {
    document.location.reload(); // die neue Version startet beim nächsten Laden der Seite
  }
}
Der Cache vor dem Cache
ngsw.json und ngsw-worker.js dürfen von CDN oder Server nie lange gecacht werden (Cache-Control: no-cache). Behält das CDN eine alte ngsw.json, erfährt der Worker nie von einer neuen Version, und die Nutzer bleiben auf der alten, solange der CDN-Cache lebt. Dateien mit Hash im Namen dürfen dagegen immutable sein.

Offline schreiben: eine Outbox

Der Service Worker cacht Lesezugriffe; deine POST-Anfragen hebt er nicht für später auf. Offline gemachte Änderungen landen in einer Outbox: Sie werden lokal gespeichert, als wartend angezeigt und gehen eine nach der anderen, in Reihenfolge, raus, wenn die Verbindung zurück ist.

LiveOffline gespeicherte Notizen
online deine echte Verbindung: online
  • Gespeicherte Notizen erscheinen hier, mit ihrem Sync-Status.
wartend
0
synchronisiert
0
Geh offline, speichere zwei Notizen und komm wieder online: Sie gehen in Reihenfolge raus. Die Demo reagiert auch auf deine echte Verbindung — schalte das WLAN aus und wieder ein.

Drei Details machen eine Outbox zuverlässig. Sie ist persistiert (hier in localStorage; IndexedDB für große Daten oder wenn ein Worker sie lesen muss), ein Reload verliert also nichts. Sie sendet ein Element nach dem anderen, der Server erhält die Änderungen also in der Reihenfolge, in der sie gemacht wurden. Und jedes Element trägt einen beim Speichern erzeugten Idempotency-Key, sodass ein halb gelungenes Senden kein Duplikat erzeugen kann — dieselbe Idee wie bei optimistischen Updates. Bei navigator.onLine ist nur false sicher: true heißt, es gibt ein Netzwerk, nicht, dass es das Internet erreicht.

import { HttpClient, HttpContext } from '@angular/common/http';
import { DOCUMENT, Service, computed, effect, inject, signal, untracked } from '@angular/core';
import { firstValueFrom } from 'rxjs';
import { IDEMPOTENCY_KEY } from './idempotency'; // siehe die Seite zu optimistischen Updates
import { injectOnline } from './online';

interface Pending {
  key: string; // Idempotency-Key, EINMAL erzeugt, wenn der Nutzer speichert
  url: string;
  body: unknown;
}

const STORAGE = 'outbox';

@Service()
export class Outbox {
  private readonly http = inject(HttpClient);
  private readonly storage = inject(DOCUMENT).defaultView?.localStorage; // undefined während SSR
  readonly online = injectOnline();
  readonly items = signal<readonly Pending[]>(JSON.parse(this.storage?.getItem(STORAGE) ?? '[]'));
  readonly waiting = computed(() => this.items().length);
  private flushing = false;

  constructor() {
    // übersteht einen Reload (IndexedDB, wenn die Daten groß sind oder ein Worker sie lesen muss)
    effect(() => this.storage?.setItem(STORAGE, JSON.stringify(this.items())));
    effect(() => {
      if (this.online()) untracked(() => void this.flush());
    });
  }

  save(url: string, body: unknown): void {
    this.items.update((list) => [...list, { key: crypto.randomUUID(), url, body }]);
    if (this.online()) void this.flush();
  }

  /** Eins nach dem anderen, in Reihenfolge. Ein Fehler stoppt die Warteschlange; das nächste "online" setzt sie fort. */
  private async flush(): Promise<void> {
    if (this.flushing) return;
    this.flushing = true;
    try {
      while (this.online() && this.items().length) {
        const [next] = this.items();
        await firstValueFrom(
          this.http.post(next.url, next.body, {
            context: new HttpContext().set(IDEMPOTENCY_KEY, next.key),
          }),
        );
        this.items.update((list) => list.slice(1));
      }
    } catch {
      // noch offline oder der Server ist down: das Element bleibt vorne in der Reihe
    } finally {
      this.flushing = false;
    }
  }
}

Wann ja, wann nein

Wann ja
  • Apps im Außendienst oder unterwegs: Inspektionen, Lieferungen, Kundenbesuche.
  • Inhalte, die man wieder liest: Dokumentation, Artikel, Kataloge.
  • Formulare, die keine Daten verlieren dürfen, wenn das Netz wegbricht.
Wann nein
  • Daten, die veraltet gefährlich sind: Börsenhandel, Live-Disposition, Notfallinformationen.
  • Interne Tools, die immer im schnellen Büronetz laufen: Die zusätzliche Komplexität bringt wenig.
  • Apps, bei denen du nicht in Cache-Invalidierung und Tests investieren kannst: cache wenigstens nur die Shell.

Häufige Stolperfallen

  • Ein CDN, das ngsw.json cacht. Die Nutzer bleiben noch lange nach dem Deploy auf der alten Version.
  • performance für Daten, die frisch sein müssen. Ein Preis von gestern, sofort und selbstbewusst angezeigt.
  • Automatisch neu laden, wenn eine Version bereit ist. Der Nutzer verliert das Formular, das er gerade ausfüllt.
  • navigator.onLine === true vertrauen. Auch Hotel-WLAN mit Login-Seite sagt „online“.
  • Eine Outbox nur im Speicher oder ohne Idempotenzschlüssel. Die erste verliert Daten beim Reload, die zweite erzeugt Duplikate beim Retry.

Spickzettel

ng add @angular/pwa              Worker + Manifest + ngsw-config.json (nur Production-Builds)
registrationStrategy             'registerWhenStable:30000': nach dem ersten Rendern
assetGroups prefetch             die App-Shell: index.html, JS, CSS, offline verfügbar
assetGroups lazy                 Bilder, Fonts: beim ersten Gebrauch gecacht
dataGroups freshness + timeout   zuerst Netzwerk; langsamer als timeout → Antwort aus dem Cache
dataGroups performance           zuerst Cache; refreshAhead aktualisiert vor maxAge im Hintergrund
maxAge                           harte Grenze: ältere Einträge fliegen raus, auch offline
SwUpdate.versionUpdates          VERSION_READY → den Nutzer fragen, beim Klick neu laden
SwUpdate.unrecoverable           die Dateien der alten Version sind weg → neu laden
checkForUpdate()                 regelmäßig, für Tabs, die tagelang offen bleiben
CDN / HTTP-Cache                 ngsw.json und ngsw-worker.js: no-cache, nie immutable
navigator.onLine                 false ist sicher, true heißt nur „es gibt ein Netzwerk“
Schreiben offline                Outbox: geordnet, persistiert, jeweils mit Idempotency-Key

Kap. 15 · 0 von 3 abgeschlossen

Lektion abgeschlossen?

Markiere sie, dann erscheint sie auf deiner Karte: im Inhaltsverzeichnis und auf der Startseite.

Wird automatisch markiert, sobald du die ganze Lektion gelesen hast.

  1. WebSockets: Echtzeit, die das Netz übersteht
  2. Optimistische Updates & Rollback
  3. Offline-first: Service Worker & Caching
Deine ganze Karte ansehen

Alle 75 Seiten · tippen zum Filtern

  • 01Was ist neu in Angular 21 & 22Alle wichtigen Änderungen in v21 und v22 in Kürze, mit Link zur Seite, die sie jeweils erklärt.Start
  • 01Deine erste App, Schritt für SchrittEine Leseliste, von einer leeren Komponente bis zur fertigen App — Signals, @for, Inputs und Outputs, ein Service und ein Formular, Schritt für Schritt.Start
  • 01Schnelle Entscheidungen„Wohin damit?“, „Signal oder Observable?“, „Shared oder Feature?“ — kurze Antworten auf Alltagsfragen.Start
  • 01Angular-Interviewfragen60 echte Interviewfragen für Junior, Mid und Senior, mit der passenden Antwort, der Nachfrage und den Warnsignalen. Dazu ein Probeinterview.Start
  • 02Standalone & BootstrapWie eine App ohne NgModule startet: bootstrapApplication, app.config.ts, imports in der Komponente.Moderne Grundlagen
  • 02Data Binding & EventsInterpolation, Property- und Attribut-Bindings, Events mit $event und Tastenfiltern und wie [( )] aufgebaut ist — was in das DOM geht und was zurückkommt.Moderne Grundlagen
  • 02Control Flow: @if, @for, @switchDie Block-Syntax, die *ngIf/*ngFor/ngSwitch ersetzt, mit track, @empty und Exhaustive Checks.Moderne Grundlagen
  • 02@let und die neuen Template-AusdrückeLokale Variablen mit @let, Arrow Functions, Spread, Regex, instanceof, Kommentare in Tags.Moderne Grundlagen
  • 02@defer — Lazy Loading in TemplatesSchwere Komponenten nur laden, wenn sie gebraucht werden: Trigger, Prefetch, Placeholder, Loading, Error.Moderne Grundlagen
  • 02Class- & Style-BindingsWarum [class.x] und [style.x] ngClass und ngStyle abgelöst haben (mit automatischer Migration ab v21).Moderne Grundlagen
  • 02Komponenten-Styles & Kapselung:host, die drei Kapselungsmodi, Theming mit CSS-Variablen und warum ::ng-deep der letzte Ausweg ist.Moderne Grundlagen
  • 02Pipes: wann und wiePure vs. Impure Pipes, eigene Pipes und wie du zwischen Pipe, computed() und Methode wählst.Moderne Grundlagen
  • 03signal() und computed()Die reaktiven Grundbausteine: beschreibbarer Zustand, abgeleiteter Zustand, Gleichheit, untracked und Regeln zur Immutability.Signals & Reaktivität
  • 03effect() — wann ja, wann neinMit Signals synchronisierte Seiteneffekte: localStorage, Logging, imperative APIs. Und ihre Stolperfallen.Signals & Reaktivität
  • 03linkedSignal() — editierbarer abgeleiteter ZustandEin Signal, das sich zurücksetzt, wenn sich seine Quelle ändert, das du aber auch manuell setzen kannst.Signals & Reaktivität
  • 03resource, rxResource, httpResourceAsynchrone Daten als Signals: status, value, error, reload, automatischer Abbruch. Stabil seit v22.Signals & Reaktivität
  • 03debounced() — verzögerte SignalsDie „Debounce“-Variante eines Signals, ohne RxJS. Perfekt für die Suche.Signals & Reaktivität
  • 03Listen: suchen, filtern, sortieren, blätternEine Kette von computed-Signals, die nur neu berechnet, was sich geändert hat — mit den Filtern in der URL, damit ein Link dieselbe Ansicht öffnet.Signals & Reaktivität
  • 03Observables von null anWas ein Observable ist, subscribe und unsubscribe, die Operatoren, die du jede Woche brauchst, cold vs. hot — und wann ein Signal reicht.Signals & Reaktivität
  • 03Signals ↔ RxJStoSignal, toObservable, takeUntilDestroyed, outputFromObservable — und wann RxJS weiterhin die richtige Wahl bleibt.Signals & Reaktivität
  • 04input() und output()Inputs als Signals (required, transform, alias) und typisierte Outputs. Daten nach unten, Events nach oben.Komponenten: Kommunikation
  • 04model() — Two-Way-BindingBanana-in-a-Box [( )] mit einer einzigen API. Wann du es nutzt und wann input + output besser ist.Komponenten: Kommunikation
  • 04viewChild & contentChildQueries als Signals: viewChild, viewChildren, contentChild, contentChildren, die Option read.Komponenten: Kommunikation
  • 04Lifecycle & DestroyRefWelche Hooks in der Signals-Ära noch zählen, afterNextRender, DestroyRef und typisiertes ngOnChanges.Komponenten: Kommunikation
  • 04Content Projectionng-content mit select, mehrere Slots, Standardinhalt und die Falle der bedingten Projektion.Komponenten: Kommunikation
  • 04ng-template & ngTemplateOutletTemplates als Werte: Render Props in Angular, typisierter Kontext und Anpassen von Komponenten.Komponenten: Kommunikation
  • 05Smart vs. DumbContainer vs. Presentational: wer den Zustand hält, wer nur anzeigt und wie du die beiden sauber trennst.Komponenten-Design
  • 05Generische Komponenten <T>Eine korrekt typisierte DataTable<T> oder Select<T>, mit Templates für Zellen.Komponenten-Design
  • 05Dynamische KomponentenNgComponentOutlet, createComponent mit inputBinding/outputBinding und ein Dashboard, das aus einer Konfiguration gebaut wird.Komponenten-Design
  • 05Direktiven & Host-KompositionAttribut-Direktiven, die host: {}-Metadaten und die Directive Composition API (hostDirectives).Komponenten-Design
  • 05Eigene Formular-ControlsFormValueControl (Signal Forms) vs. ControlValueAccessor: eine Sternebewertung, in beiden Varianten.Komponenten-Design
  • 05Change DetectionOnPush ist ab v22 der Standard, zone.js entfällt ab v21. Was das Rendering auslöst und wie du dir nicht die Finger verbrennst.Komponenten-Design
  • 06inject() & @Service()Der neue @Service()-Decorator ab v22, inject() vs. Konstruktor und der Injection-Kontext.Dependency Injection
  • 06Provider & die Injector-HierarchieRoot vs. Route vs. Komponente, useClass/useValue/useFactory/useExisting und die Modifier optional/self/skipSelf.Dependency Injection
  • 06InjectionToken & provideX()Typisierte Konfiguration, provideFeature()-Funktionen, makeEnvironmentProviders und Initializer.Dependency Injection
  • 06injectAsync() — Lazy ServicesLade einen schweren Service erst, wenn du ihn brauchst, mit Prefetch im Leerlauf.Dependency Injection
  • 07Ordnerstrukturcore / shared / features, was in welchen Ordner gehört und wie ein Feature von innen aussieht.Architektur der Anwendung
  • 07Shared vs. FeatureWann du eine Komponente nach Shared verschiebst und (vor allem) wann NICHT. Eine konkrete Checkliste.Architektur der Anwendung
  • 07Interfaces & ModelleInline-Interface oder eigene Datei? DTO vs. Domänenmodell, type vs. interface, wohin damit.Architektur der Anwendung
  • 07State Management mit SignalsEinfache Signal-Stores, Fassaden, lokaler vs. globaler Zustand und wann du NgRx brauchst.Architektur der Anwendung
  • 07Styleguide & NamensgebungDie aktuellen offiziellen Konventionen: Dateinamen ohne Suffixe, protected, readonly, Reihenfolge der Member.Architektur der Anwendung
  • 07Barrels, Aliase & Grenzenindex.ts, Pfad-Aliase, die öffentliche API eines Features und Abhängigkeitsregeln, die sich automatisch prüfen lassen.Architektur der Anwendung
  • 07Fehler: @boundary & ErrorHandlerDer neue @boundary-Block ab v22.2, der globale ErrorHandler, HTTP-Fehler und Fehler aus resource.Architektur der Anwendung
  • 08Modernes Routing & Lazy LoadingloadComponent, Child Routes, Parameter als Inputs und Parameter-Vererbung (neuer Standard in v22).Routing
  • 08Guards & ResolvercanActivate, canMatch, canDeactivate und resolve als Funktionen, mit Redirects über UrlTree / RedirectCommand.Routing
  • 09Signal Forms — die GrundlagenFormulare auf Basis von Signals: form(), [formField], schemabasierte Validierung. Stabil seit v22.Formulare
  • 09Signal Forms — fortgeschrittenEigene und feldübergreifende Validierung, async/HTTP mit Debounce, dynamische Listen, disabled/hidden, wiederverwendbare Schemas.Formulare
  • 09Typisierte Reactive FormsTypisierte FormGroup, nonNullable, FormArray — und wie sie neben Signal Forms bestehen.Formulare
  • 10HttpClient, Interceptors & die API-SchichtHttpClient ohne Setup (v21), Fetch als Standard (v22), funktionale Interceptors und eine API-Schicht mit DTO-Mapping.HTTP & Daten
  • 11Performance — eine ChecklisteWas wirklich zählt: OnPush + Signals, track, @defer, Lazy Routes, Bilder, Bundles und Hydration.Qualität & Performance
  • 11Testen mit VitestVitest ist ab v21 der Standard-Runner. TestBed, Komponenten mit Signals, Services, HTTP und Harnesses.Qualität & Performance
  • 11DevTools: ein Blick in deine AppChrome DevTools und Angular DevTools Schritt für Schritt: was jedes Panel zeigt, mit Übungen, die auf dieser Website funktionieren.Qualität & Performance
  • 11Angular AriaHeadless, barrierefreie Komponenten, die du nach Belieben stylst: Tabs, Accordion, Menü, Listbox...Qualität & Performance
  • 12SSR, Prerendering & Render ModesWann auf dem Server gerendert wird, wann beim Build und wann nur im Browser: RenderMode pro Route, app.routes.server.ts und die echten Kosten.SSR & Hydration
  • 12Hydration: Event Replay & inkrementellWie der Browser das Server-HTML übernimmt, ohne es neu zu rendern: vollständige Hydration, Event Replay, @defer (hydrate on …) und Mismatch-Fehler.SSR & Hydration
  • 12Servertauglicher Codewindow gibt es auf dem Server nicht: PLATFORM_ID, afterNextRender, DOCUMENT, TransferState, der HTTP-Cache und PendingTasks.SSR & Hydration
  • 13Micro FrontendsWann es sich lohnt, eine App in mehrere Deployments aufzuteilen und wann es nur Komplexität ist: Native Federation, Module Federation, iframes, Web Components.Architektur im großen Maßstab
  • 13Web Components mit Angular ElementscreateCustomElement: eine Angular-Komponente, die überall als HTML-Tag nutzbar ist, plus Kommunikation zwischen Apps über Events und BroadcastChannel.Architektur im großen Maßstab
  • 13Monorepo, Bibliotheken & GrenzenEin Workspace mit mehreren Apps und Bibliotheken: ng generate library, Nx, Secondary Entry Points, Publishing und Abhängigkeitsregeln.Architektur im großen Maßstab
  • 13Hexagonale Architektur (Ports & Adapters)Eine Domäne ohne Angular, Ports als abstrakte Klassen und austauschbare Adapter: HTTP, localStorage oder In-Memory, ohne die UI anzufassen.Architektur im großen Maßstab
  • 14Signals unter der HaubeDer reaktive Graph: Producer und Consumer, Push-Pull, warum computed lazy und glitch-frei ist, das Diamond-Problem und wann Effects laufen.Fortgeschrittene Reaktivität
  • 14Fortgeschrittenes RxJS: Operatoren höherer OrdnungswitchMap, mergeMap, concatMap und exhaustMap an einem Live-Diagramm, dazu Retry mit Backoff, shareReplay und wie du Leaks vermeidest.Fortgeschrittene Reaktivität
  • 14NgRx SignalStoreState Management im großen Stil auf Signals: withState, withComputed, withMethods, rxMethod, Entities und Hooks — und wann ein einfacher Store reicht.Fortgeschrittene Reaktivität
  • 14Zustandsautomaten mit SignalsKeine unmöglichen Zustände mehr: ein typisierter Automat auf Signals, mit Übergängen, Guards und einem Live-Zustandsdiagramm.Fortgeschrittene Reaktivität
  • 15WebSockets: Echtzeit, die das Netz überstehtEin typisierter Socket als Signals: Reconnect mit Backoff und Jitter, Heartbeat, ein Postausgang im Offline-Modus und SSR-Sicherheit.Echtzeit & offline
  • 15Optimistische Updates & RollbackEine sofortige UI, die ehrlich bleibt: Snapshot und Rollback, Antworten in falscher Reihenfolge, Idempotenzschlüssel.Echtzeit & offline
  • 15Offline-first: Service Worker & CachingDer Angular Service Worker: Caching-Strategien, Update-Hinweise und ein Postausgang für Änderungen, die offline entstehen.Echtzeit & offline
  • 16Web WorkersSchwere Berechnungen, ohne die UI zu blockieren: ein echter Worker in der Seite, Message Passing und wann es sich nicht lohnt.Fortgeschrittene UI & Performance
  • 16Riesige Listen: Virtual Scroll100.000 Zeilen ohne Ruckeln: CDK Virtual Scroll, itemSize, trackBy und die Alternativen (Paginierung, Infinite Scroll).Fortgeschrittene UI & Performance
  • 16Moderne Animationen & View Transitionsanimate.enter und animate.leave statt des veralteten @angular/animations, CSS-Transitions und View Transitions bei der Navigation.Fortgeschrittene UI & Performance
  • 16Memory Leaks finden und behebenSubscriptions, Timer und Listener, die ihre Komponente überleben – wie du sie in den DevTools findest und schließt.Fortgeschrittene UI & Performance
  • 17Sicherheit: XSS, Sanitizing & CSPWas Angular automatisch gegen XSS tut, wann bypassSecurityTrust gefährlich wird, dazu CSP mit Nonce, Trusted Types und XSRF.Sicherheit & Globalisierung
  • 17Authentifizierung: Tokens & RefreshEin Interceptor, der das Token anhängt, bei 401 einmal erneuert und die wartenden Requests wiederholt — dazu, wo du das Token aufbewahrst.Sicherheit & Globalisierung
  • 17OAuth 2.1 & OpenID Connect mit PKCEDer Authorization-Code-Flow mit PKCE Schritt für Schritt: Verifier und Challenge, State und Nonce, das ID-Token und warum ein BFF sicherer ist.Sicherheit & Globalisierung
  • 17Internationalisierung (i18n)$localize, das i18n-Attribut, ICU plural/select, ein Build pro Sprache vs. Übersetzungen zur Laufzeit und Formatierung nach Locale.Sicherheit & Globalisierung