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.
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.
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.
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.
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:
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:
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:
on viewport && after 2s)Die Deferrable Views bieten eine deklarative Möglichkeit, das Laden von Komponenten zu optimieren und die Erstladezeit zu verbessern.
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:
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:
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:
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:
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:
takeUntilDestroyed Operator für RxJSAngular 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:
font-display
StrategienAngular 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:
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: