313 lines
8.4 KiB
Markdown
313 lines
8.4 KiB
Markdown
# 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
|