Project-Image-Uploader/docs/FEATURE_PLAN-preview-images.md
matthias.lotz 6ee736bcea docs: add feature plan for preview images
- Architecture overview: previews/ directory structure
- Backend: Sharp library for image processing
- DB schema extension: preview_path column
- Frontend: Use previews in galleries, keep originals in slideshow
- Estimated effort: 12-22h (2-3 days)
- Expected improvement: ~95% size reduction, ~96% faster load times

Ref: feature/preview-images
2025-10-29 23:34:08 +01:00

8.4 KiB
Raw Blame History

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:

npm install sharp --save

Datenbankschema-Erweiterung

-- 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:

{
  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)

-- 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

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:

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):

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:

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)

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