wasm migration plan added

This commit is contained in:
Wieland, Marc
2026-06-08 15:50:42 +02:00
parent dd2d47e57d
commit fe294e288a
2 changed files with 183 additions and 0 deletions
BIN
View File
Binary file not shown.
+183
View File
@@ -0,0 +1,183 @@
# 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.