Files
timetracker/wasm.md
T
2026-06-08 15:50:42 +02:00

184 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Blazor WASM Migration Aufwandsanalyse
> Analysiert am 08.06.2026
> Aktueller Stack: Blazor Server (.NET 10, InteractiveServer, SQLite, MudBlazor 9.4)
---
## TL;DR
Eine vollständige Migration auf Blazor WebAssembly ist **technisch möglich**, aber ein **erheblicher Umbau**. Der Aufwand liegt bei schätzungsweise **35 Wochen** für einen Entwickler. Der Hauptgrund: Blazor WASM läuft vollständig im Browser kein direkter DB-Zugriff, keine Cookie-Auth serverseitig, keine gemeinsamen In-Process-Events zwischen Nutzern.
**Empfehlung:** Hybrid-Modell (Blazor Auto oder WASM + ASP.NET Core API auf demselben Server) ist der pragmatischste Weg.
---
## Was WASM bringt
| Vorteil | Erklärung |
|---|---|
| Keine SignalR-Verbindung nötig | WASM lädt den Code einmalig herunter, kein dauerhafter WebSocket |
| Besser skalierbar | Server hält keine Circuits pro User im Speicher |
| Offline-fähig (theoretisch) | Progressive Web App möglich |
| Geringere Serverauslastung | UI-Logik läuft im Browser |
**Aber Achtung:** Der initiale Download ist größer (~1020 MB .NET Runtime im Browser), erste Ladezeit spürbar langsamer als Blazor Server.
---
## Aktuelle Blocker (nach Schwere)
### 🔴 KRITISCH muss komplett umgebaut werden
#### 1. Datenbankzugriff EF Core / SQLite
Alle drei Services greifen direkt per `IDbContextFactory<TimetrackerDbContext>` auf die SQLite-DB zu:
- `AuthService` → Login, Registrierung, User-CRUD
- `TimetrackerService` → Arbeitstage, Pausen, Einstellungen, Urlaub, Überstunden
- `HolidayService` → Feiertage speichern/lesen
**WASM kann nicht direkt auf eine Datenbank zugreifen.** Browser hat keinen Dateisystemzugriff.
**Lösung:** Alle Service-Methoden als REST-API-Endpoints auf dem Server exponieren. WASM-Client ruft diese per `HttpClient` auf.
**Aufwand:** ~1015 Tage (je nach gewähltem API-Stil: Minimal API vs. Controller)
---
#### 2. Cookie-Authentifizierung
Aktuell läuft der gesamte Auth-Flow serverseitig:
- `POST /auth/login``HttpContext.SignInAsync()` → Cookie setzen
- `GET /auth/logout``HttpContext.SignOutAsync()`
- Blazor-Komponenten lesen den Cookie über `CascadingAuthenticationState`
In WASM gibt es keinen direkten Zugriff auf `HttpContext`. Die Cookie-Auth muss weiterhin **serverseitig** verbleiben, aber das Login-Formular muss über die API kommunizieren.
**Lösung A (einfacher):** Cookie-Auth beibehalten, aber Login-Formular als API-Call (kein HTML-Form-Post mehr). WASM erhält Auth-State über einen `/auth/me`-Endpoint.
**Lösung B (aufwändiger):** JWT-Token-Auth einführen, Token im Browser-Speicher halten.
**Empfehlung:** Lösung A, da Cookie-Auth bereits implementiert ist und sicherer gegen XSS ist als localStorage-JWTs.
**Aufwand:** ~34 Tage
---
#### 3. Projektstruktur neue Build-Konfiguration
Aktuell: 1 Projekt (`Microsoft.NET.Sdk.Web`), alles in einem.
WASM benötigt mindestens:
- **`timetracker.Client`** Blazor WASM-Projekt (läuft im Browser)
- **`timetracker.Server`** ASP.NET Core-Projekt (hostet API + WASM-App)
- Optional: **`timetracker.Shared`** DTOs/Models geteilt zwischen Client & Server
Alle `@inject`-Direktiven, die auf Server-Services zeigen, müssen im Client auf `HttpClient`-basierte Services umgestellt werden.
**Aufwand:** ~34 Tage (Projektaufspaltung, DI-Umverdrahtung)
---
### ⚠️ MITTEL umbaubar, aber aufwändig
#### 4. UserNotificationService (Live-Updates)
Aktuell: Singleton mit C#-Events, der zwischen Blazor Server-Circuits kommuniziert:
- Admin löscht User → Event feuert → alle aktiven `MainLayout`-Instanzen reagieren
- Neuer User registriert → `AdminUsers` aktualisiert sich live
In WASM gibt es keine gemeinsamen In-Process-Events. Jeder Browser ist isoliert.
**Lösung:** **SignalR Hub** einführen. Server sendet Push-Nachrichten an alle verbundenen Clients.
```
[Browser A Admin] [Server] [Browser B normaler User]
löscht User C → Hub.Clients.All.SendAsync → empfängt "UserDeleted(C)"
→ NavigateTo("/auth/logout")
```
**Aufwand:** ~23 Tage (Hub einrichten, Client-seitig `HubConnection` einbauen)
---
#### 5. Formular-basiertes Login/Register
Login und Registrierung verwenden aktuell native HTML-Forms (`method="post"`) die direkt an `/auth/login` und `/auth/register` posten. Das funktioniert in WASM nicht mehr sauber, weil WASM SPA-Navigation nutzt.
**Lösung:** Login-Formular auf `@code`-basierten `HttpClient.PostAsync`-Call umstellen, Redirect über `NavigationManager`.
**Aufwand:** ~1 Tag
---
#### 6. Docker-Deployment
Aktuell: 1 Container, alles drin.
WASM + API = zwei Artefakte:
- Die WASM-App sind statische Dateien (HTML/JS/WASM)
- Die API läuft als ASP.NET Core-Server
**Lösung A (einfach):** Hosted WASM API-Server liefert auch die WASM-Dateien aus (1 Container, 1 Dockerfile, wie heute)
**Lösung B (komplex):** Getrennte Container (Nginx für WASM, API separat)
**Empfehlung:** Lösung A (Hosted WASM) minimaler Deployment-Overhead.
**Aufwand:** ~0,5 Tage bei Lösung A
---
### ✅ KEIN UMBAU NÖTIG
| Komponente | Warum kein Umbau |
|---|---|
| **MudBlazor 9.4** | Vollständig WASM-kompatibel |
| **Alle `.razor`-Seiten (UI)** | Markup bleibt identisch, nur `@inject` ändert sich |
| **Entity Models** (User, WorkDay, etc.) | Können ins Shared-Projekt verschoben werden |
| **HttpClient für Feiertage** (nager.at) | Funktioniert in WASM nativ |
| **Business-Logik in Komponenten** | Bleibt unverändert |
| **CSS / MudBlazor Theme** | Unverändert |
---
## Gesamtaufwand-Schätzung
| Aufgabe | Geschätzter Aufwand |
|---|---|
| Projektstruktur aufteilen (Client/Server/Shared) | 23 Tage |
| REST-API für TimetrackerService | 45 Tage |
| REST-API für AuthService + HolidayService | 23 Tage |
| Cookie-Auth auf API-Flow umstellen | 23 Tage |
| Client-Services (HttpClient-basiert) erstellen | 34 Tage |
| SignalR für Live-Notifications | 23 Tage |
| Login/Register-Formulare anpassen | 1 Tag |
| Docker/Deployment anpassen | 0,51 Tag |
| Testen & Debugging | 23 Tage |
| **Gesamt** | **~1826 Tage** |
---
## Empfohlene Alternative: Blazor Auto
.NET 8+ bietet **Blazor Auto**-Rendermodus: Seiten starten als Server-Rendering, wechseln dann automatisch zu WASM sobald die Runtime heruntergeladen ist. Das gibt sofortige Interaktivität (Server) + langfristig WASM-Performance.
**Vorteil:** DB-Zugriff und Auth bleiben wie heute, kein API-Layer nötig.
**Aufwand:** ~35 Tage (Projektstruktur, Shared-Projekt, WASM-Client-Projekt anlegen).
**Für dieses Projekt sehr empfehlenswert**, da:
1. Minimaler Umbau der bestehenden Logik
2. Spürbare Performance-Verbesserung nach erstem Laden
3. Kein SignalR-Umbau notwendig (Server-Circuit bleibt beim ersten Laden aktiv)
---
## Fazit
| Option | Aufwand | Performance-Gewinn | Empfehlung |
|---|---|---|---|
| Blazor WASM (pure) | ~2025 Tage | Hoch (nach erstem Laden) | Nur bei hoher Nutzerzahl sinnvoll |
| Blazor Auto | ~35 Tage | Mittel-Hoch | ✅ **Empfohlen** |
| Blazor Server (wie heute) | 0 | | Gut für kleine Nutzerzahl |
Für den aktuellen Use-Case (internes Uni-Tool, überschaubare Nutzerzahl) ist **Blazor Auto** das beste Kosten-Nutzen-Verhältnis. Eine vollständige WASM-Migration lohnt sich erst, wenn die App deutlich mehr parallele User hat oder offline-Fähigkeit gefordert wird.