# Feature: Preview-Bilder für Galerie **Branch:** `feature/preview-images` **Datum:** 29. Oktober 2025 ## 🎯 Ziel Generierung und Verwendung von optimierten Preview-Bildern (Thumbnails) für Galerie-Ansichten, um: - Ladezeiten drastisch zu reduzieren - Bandbreite zu sparen - User Experience zu verbessern - Mobile Performance zu optimieren --- ## 📐 Architektur-Überblick ### Aktuelle Situation - Bilder werden in voller Auflösung in Galerien geladen - Path: `backend/src/data/images/` (Original-Bilder) - Keine Thumbnails oder Preview-Varianten ### Ziel-Architektur ``` backend/src/data/ ├── images/ # Original-Bilder (unverändert) │ └── X_JeZj0TsQ.JPG └── previews/ # NEU: Preview-Bilder (optimiert) └── X_JeZj0TsQ.JPG (oder .webp) ``` ### Thumbnail-Spezifikationen - **Größe:** Max. 800px Breite (beibehält Aspect Ratio) - **Format:** JPEG (85% Qualität) oder WebP (falls unterstützt) - **Verwendung:** Galerie-Views (GroupsOverviewPage, ModerationGroupsPage) - **Original:** Slideshow-View und Download behalten Original-Bilder --- ## 🔧 Technische Implementierung ### Backend: Sharp Library **Warum Sharp?** - Schnell (nutzt libvips) - Unterstützt JPEG, PNG, WebP - Läuft in Node.js ohne externe Binaries - Unterstützt Resize, Optimize, Format-Konvertierung **Installation:** ```bash npm install sharp --save ``` ### Datenbankschema-Erweiterung ```sql -- Erweitere images Tabelle um preview_path ALTER TABLE images ADD COLUMN preview_path TEXT; -- Index für schnelle Abfragen CREATE INDEX IF NOT EXISTS idx_images_preview_path ON images(preview_path); ``` --- ## 📋 Implementierungs-Phasen ### Phase 1: Backend - Preview-Generierung (6-10h) #### 1.1 Service-Layer erstellen **Datei:** `backend/src/services/ImagePreviewService.js` **Funktionen:** - `generatePreview(originalPath, outputPath, options)` - Generiert einzelnes Preview - `generatePreviewsForGroup(groupId)` - Batch-Generierung für Upload-Gruppe - `cleanupOrphanedPreviews()` - Entfernt nicht mehr verwendete Previews - `getPreviewPath(originalFileName)` - Gibt Preview-Pfad zurück **Optionen:** ```javascript { width: 800, // Max-Breite in px quality: 85, // JPEG-Qualität format: 'jpeg', // 'jpeg' oder 'webp' withoutEnlargement: true // Keine Vergrößerung kleiner Bilder } ``` #### 1.2 Upload-Route erweitern **Datei:** `backend/src/routes/upload.js` & `backend/src/routes/batchUpload.js` - Nach erfolgreichem Upload: Preview-Generierung triggern - Preview-Pfad in DB speichern - Fehlerbehandlung: Bei Preview-Fehler Upload trotzdem erfolgreich #### 1.3 DB-Schema Migration **Datei:** `backend/src/database/migrations/003_add_preview_path.sql` (NEU) ```sql -- Migration 003: Add preview_path column ALTER TABLE images ADD COLUMN preview_path TEXT; CREATE INDEX IF NOT EXISTS idx_images_preview_path ON images(preview_path); ``` **Datei:** `backend/src/database/DatabaseManager.js` - Erweitere `initDatabase()` um Migration-Support - Auto-run Migrations beim Start #### 1.4 API-Endpunkte erweitern **Bestehende Endpoints anpassen:** - `GET /groups` - Rückgabe mit `previewPath` für jedes Bild - `GET /groups/:groupId` - Rückgabe mit `previewPath` - `GET /moderation/groups` - Rückgabe mit `previewPath` **Neue Endpoints (optional):** - `POST /groups/:groupId/regenerate-previews` - Regeneriert Previews für Gruppe - `GET /previews/:fileName` - Serve Preview-Bilder (analog zu `/upload/:fileName`) #### 1.5 Constants & Config **Datei:** `backend/src/constants.js` ```javascript const PREVIEW_FS_DIR = 'data/previews'; const PREVIEW_CONFIG = { width: 800, quality: 85, format: 'jpeg' }; ``` --- ### Phase 2: Backend - Batch-Migration bestehender Bilder (2-4h) #### 2.1 Migration-Script **Datei:** `backend/src/scripts/generatePreviewsForExisting.js` - Liest alle Bilder aus DB ohne `preview_path` - Generiert Previews für alle bestehenden Bilder - Aktualisiert DB mit Preview-Pfaden - Progress-Logging **Ausführung:** ```bash node backend/src/scripts/generatePreviewsForExisting.js ``` Oder als Express-Endpoint für Admin: - `POST /admin/migrate-previews` (mit Basic Auth) --- ### Phase 3: Frontend - Preview-Nutzung (3-6h) #### 3.1 API-Response erweitern **Typ-Definitionen (optional):** ```typescript interface Image { id: number; fileName: string; originalName: string; filePath: string; // Original-Bild previewPath?: string; // NEU: Preview-Bild uploadOrder: number; fileSize: number; mimeType: string; } ``` #### 3.2 Component Updates **Dateien zu ändern:** - `frontend/src/Components/ComponentUtils/GroupCard.js` - `frontend/src/Components/Pages/GroupsOverviewPage.js` - `frontend/src/Components/Pages/ModerationGroupsPage.js` **Logik:** ```javascript const imageSrc = image.previewPath || image.filePath; // Fallback auf Original, falls Preview fehlt ``` #### 3.3 Slideshow beibehält Original **Datei:** `frontend/src/Components/Pages/SlideshowPage.js` - **Keine Änderung** - Slideshow nutzt weiterhin `filePath` (Original) --- ### Phase 4: Testing & Optimierung (2-4h) #### 4.1 Unit Tests - `ImagePreviewService.test.js` - Service-Logik - Test mit verschiedenen Bildformaten (JPEG, PNG) - Error-Handling Tests #### 4.2 Integration Tests - Upload → Preview-Generierung → DB-Update - API-Response enthält `previewPath` - Frontend lädt Preview-Bilder #### 4.3 Performance-Messung - Vergleich Ladezeiten: Original vs. Preview - Bundle-Size (Sharp Library Impact) - Memory-Usage bei Batch-Generierung #### 4.4 Cleanup & Docs - `README.md` Update mit Preview-Feature - `CHANGELOG.md` Eintrag - Code-Kommentare & JSDoc --- ## ⏱️ Zeitschätzung | Phase | Aufgabe | Geschätzt | |-------|---------|-----------| | 1.1 | ImagePreviewService | 2-3h | | 1.2 | Upload-Route erweitern | 1-2h | | 1.3 | DB-Migration | 1h | | 1.4 | API-Endpoints | 1-2h | | 1.5 | Config/Constants | 0.5h | | 2.1 | Batch-Migration Script | 2-4h | | 3.1-3.3 | Frontend Updates | 3-6h | | 4.1-4.4 | Testing & Docs | 2-4h | | **Gesamt** | | **12-22h** | **Realistische Schätzung:** 2-3 Arbeitstage --- ## 🚀 Deployment-Strategie ### Schritt 1: Backend-Deploy mit Preview-Generierung - Deploy neuer Backend-Code - DB-Migration läuft automatisch beim Start - Neue Uploads erhalten automatisch Previews ### Schritt 2: Batch-Migration (einmalig) ```bash docker exec image-uploader-backend node src/scripts/generatePreviewsForExisting.js ``` oder via Admin-Endpoint ### Schritt 3: Frontend-Deploy - Deploy Frontend mit Preview-Support - Fallback auf Original-Bilder bleibt aktiv ### Rollback-Plan - Preview-Feature ist opt-in (Fallback auf `filePath`) - Bei Problemen: Frontend-Rollback ohne Backend-Änderung nötig --- ## 📊 Erwartete Verbesserungen ### Dateigrößen (Beispiel) - **Original JPEG (3000x2000px):** ~2-3 MB - **Preview JPEG (800x533px, 85%):** ~80-150 KB - **Einsparung:** ~95% ### Ladezeiten (Galerie mit 20 Bildern) - **Vorher:** 20 × 2.5 MB = 50 MB - **Nachher:** 20 × 100 KB = 2 MB - **Verbesserung:** ~96% schneller --- ## ⚠️ Risiken & Mitigation ### Risiko 1: Sharp Build-Fehler in Docker **Mitigation:** - Alpine-kompatible Sharp-Version testen - Falls nötig: `python3`, `make`, `g++` in Dockerfile hinzufügen ### Risiko 2: Disk-Space Verdopplung **Mitigation:** - Previews sind ~5% der Original-Größe - Cleanup-Script für verwaiste Previews - Optional: alte Previews nach X Tagen löschen ### Risiko 3: CPU-Last bei Batch-Migration **Mitigation:** - Batch-Processing mit Chunk-Size (z.B. 10 Bilder parallel) - Progress-Logging - Optional: Background-Job Queue (Bull, Agenda) --- ## 🔄 Zukünftige Erweiterungen - **WebP-Support:** Kleinere Dateien, bessere Compression - **Responsive Previews:** Mehrere Größen (400px, 800px, 1200px) - **Lazy-Loading:** Intersection Observer für On-Demand-Loading - **CDN-Integration:** Previews auf S3/CloudFront auslagern - **Image-Optimization:** Auto-Rotation (EXIF), Strip Metadata --- ## 📝 Acceptance Criteria - [ ] Neue Uploads generieren automatisch Previews - [ ] Bestehende Bilder haben Previews nach Migration - [ ] Galerie-Views laden Preview-Bilder (keine Originals) - [ ] Slideshow lädt weiterhin Original-Bilder - [ ] API liefert sowohl `filePath` als auch `previewPath` - [ ] Fallback auf Original funktioniert, wenn Preview fehlt - [ ] Ladezeit-Verbesserung messbar (>80%) - [ ] Tests bestehen (Unit + Integration) - [ ] Dokumentation aktualisiert --- **Erstellt am:** 29. Oktober 2025 **Zuletzt aktualisiert:** 29. Oktober 2025