36 Performance-Optimierung in Angular

36.1 Einleitung

Die Performance einer Angular-Anwendung ist ein entscheidender Faktor für die Benutzererfahrung. Mit der zunehmenden Komplexität moderner Webanwendungen wird die Optimierung der Leistung immer wichtiger. Angular bietet zahlreiche Möglichkeiten, die Performance Ihrer Anwendungen zu verbessern – von der initialen Ladezeit über das Rendering bis hin zur allgemeinen Anwendungseffizienz.

In diesem Kapitel werden wir verschiedene Strategien und Techniken zur Performance-Optimierung in Angular untersuchen. Wir werden dabei sowohl etablierte Konzepte als auch neuere Features betrachten, die mit aktuellen Angular-Versionen eingeführt oder verbessert wurden.

36.2 Verständnis der Angular Performance-Metriken

Bevor wir mit konkreten Optimierungen beginnen, ist es wichtig zu verstehen, welche Metriken für die Performance einer Angular-Anwendung relevant sind:

Diese Web Vitals sind entscheidend für das Benutzererlebnis und werden von Angular mit Tools zur Messung und Optimierung unterstützt.

36.3 Build-Optimierungen in Angular

Angular bietet verschiedene Möglichkeiten zur Optimierung des Build-Prozesses, um kleinere und schnellere Bundles zu erzeugen:

// angular.json
{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "options": {
            "optimization": true,
            "budgets": [
              {
                "type": "initial",
                "maximumWarning": "500kb",
                "maximumError": "1mb"
              },
              {
                "type": "anyComponentStyle",
                "maximumWarning": "2kb",
                "maximumError": "4kb"
              }
            ],
            "outputHashing": "all"
          },
          "configurations": {
            "production": {
              "buildOptimizer": true,
              "aot": true,
              "extractLicenses": true
            }
          }
        }
      }
    }
  }
}

Angular verbessert die Build-Optimierung durch:

Die @angular/build API bietet zusätzliche programmatische Kontrolle über den Build-Prozess.

36.4 Zoneless Change Detection

Eine wichtige Entwicklung in Angular ist die zonenlose Change Detection, die mit dem Signal-basierten Reaktivitätssystem eingeführt wurde:

// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { provideZonelessChangeDetection } from '@angular/core';

bootstrapApplication(AppComponent, {
  providers: [
    provideZonelessChangeDetection()
  ]
}).catch(err => console.error(err));

Vorteile der zonenlosen Change Detection:

Die zonenlose Change Detection ist mit dem Router, Forms und HTTP-Modul integriert.

36.5 Signal-basierte Reaktivität für Performancegewinn

Die in Angular integrierte Signal-API bietet erhebliche Performancevorteile:

import { Component, signal, computed } from '@angular/core';

@Component({
  selector: 'app-performance-example',
  template: `
    <div>Ergebnis: {{ result() }}</div>
    <button (click)="increment()">Erhöhen</button>
  `
})
export class PerformanceExampleComponent {
  count = signal(0);
  multiplier = signal(10);
  
  // Wird nur neu berechnet, wenn count oder multiplier sich ändern
  result = computed(() => this.count() * this.multiplier());
  
  increment() {
    this.count.update(value => value + 1);
  }
}

Signale bieten:

36.6 Hydration und SSR mit Angular

Angular bietet verbesserte Hydration und Server-Side Rendering (SSR):

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideClientHydration } from '@angular/platform-browser';

export const appConfig: ApplicationConfig = {
  providers: [
    provideClientHydration({
      enableTransferState: true,
      environmentTransferState: true
    })
  ]
};

Die Verbesserungen umfassen:

36.7 Deferrable Views für optimiertes Laden

Angular hat das Konzept der Deferrable Views eingeführt:

// Komponenten-Template
<div>
  Kritischer Inhalt hier...
  
  @defer (on viewport) {
    <app-heavy-component />
  } @loading {
    <app-skeleton-loader />
  } @error {
    <app-error-state />
  } @placeholder (minimum 500ms) {
    <div>Wird geladen...</div>
  }
</div>

Features der Deferrable Views:

Die Deferrable Views bieten eine deklarative Möglichkeit, das Laden von Komponenten zu optimieren und die Erstladezeit zu verbessern.

36.8 Webpack und Esbuild Optimierungen

Angular bietet Unterstützung für moderne Build-Tools:

// angular.json
{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser-esbuild",
          "options": {
            "optimization": true,
            "commonChunk": true,
            "vendorChunk": true
          }
        }
      }
    }
  }
}

Die Build-Optimierungen umfassen:

36.9 Web Workers für rechenintensive Aufgaben

Angular vereinfacht die Integration von Web Workers:

// worker.ts
/// <reference lib="webworker" />

addEventListener('message', ({ data }) => {
  const result = performComplexCalculation(data);
  postMessage(result);
});

function performComplexCalculation(data) {
  // Komplexe Berechnungen hier
  return transformedData;
}
// component.ts
import { Component, inject } from '@angular/core';
import { NgWebWorkerClient } from '@angular/core/web-worker';

@Component({
  selector: 'app-heavy-calculation',
  template: '...'
})
export class HeavyCalculationComponent {
  private workerClient = inject(NgWebWorkerClient);
  
  performCalculation(data: any) {
    this.workerClient.connectWith('./worker.js')
      .postMessage(data)
      .subscribe(result => {
        // Mit dem Ergebnis arbeiten
      });
  }
}

Angular verbessert die Web Worker Integration durch:

36.10 Verbesserte OnPush-Strategie und Memoization

Angular optimiert die OnPush Change-Detection-Strategie:

import { Component, ChangeDetectionStrategy, input, memoize } from '@angular/core';

@Component({
  selector: 'app-optimized-list',
  template: `
    <div *ngFor="let item of items(); trackBy: trackById">
      {{ item.name }}
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class OptimizedListComponent {
  items = input.required<Item[]>();
  
  // Memoization-Funktionen in Angular
  trackById = memoize((index: number, item: Item) => item.id);
}

Die OnPush-Strategie wurde durch folgende Verbesserungen optimiert:

36.11 Angular DevTools und Performance-Profiling

Angular erweitert die DevTools mit fortschrittlichen Performance-Profiling-Funktionen:

// Aktivierung erweiterter Profiling-Funktionen
import { enableDebugTools } from '@angular/platform-browser';
import { ApplicationRef, isDevMode } from '@angular/core';

bootstrapApplication(AppComponent)
  .then(appRef => {
    if (isDevMode()) {
      enableDebugTools(appRef);
    }
  })
  .catch(err => console.error(err));

Die DevTools bieten:

36.12 Memory Management und Leak Prevention

Angular führt Werkzeuge zur Vermeidung von Speicherlecks ein:

import { Component, OnDestroy, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-memory-example',
  template: '...'
})
export class MemoryExampleComponent {
  private data$ = someObservable.pipe(
    takeUntilDestroyed()  // Automatische Bereinigung
  ).subscribe(/* ... */);
}

Memory-Management-Funktionen in Angular:

36.13 Asset-Optimierung

Angular bietet Asset-Optimierung:

// angular.json
{
  "projects": {
    "my-app": {
      "architect": {
        "build": {
          "options": {
            "assets": [
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "/assets/"
              }
            ],
            "stylePreprocessorOptions": {
              "includePaths": ["src/styles"]
            },
            "sourceMap": true,
            "namedChunks": true
          }
        }
      }
    }
  }
}

Die Asset-Optimierungen umfassen:

36.14 Route-basierte Code-Splitting-Optimierungen

Angular bietet Möglichkeiten für Route-basiertes Code-Splitting:

// app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.routes')
      .then(m => m.ADMIN_ROUTES),
    data: {
      preload: true, // Für PreloadAllModules Strategie
      loadBehavior: 'eager' // Neuere Option in Angular
    }
  }
];

Die Verbesserungen umfassen:

36.15 Standalone Components und leichtgewichtige Dependency Injection

Angular optimiert die Leistung von Standalone Components und der Dependency Injection:

// standalone.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-performance-optimized',
  standalone: true,
  imports: [/* Minimierte Importe */],
  template: `<div>Optimierte Komponente</div>`
})
export class PerformanceOptimizedComponent {
  // Leichtgewichtige Implementation
}

Die Verbesserungen umfassen: