cms.c2sgmbh/docs/anleitungen/BILDOPTIMIERUNG.md
Martin Porwoll a88e4f60d0 test: add E2E and integration tests with documentation
Tests:
- Update frontend.e2e.spec.ts with locale testing
- Add search.e2e.spec.ts for search functionality
- Add i18n.int.spec.ts for localization tests
- Add search.int.spec.ts for search integration
- Update playwright.config.ts

Documentation:
- Add CLAUDE.md with project instructions
- Add docs/ directory with detailed documentation
- Add scripts/ for utility scripts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 08:19:52 +00:00

7.3 KiB

Bildoptimierung - Dokumentation

Übersicht

Die Media Collection nutzt Sharp für automatische Bildoptimierung. Beim Upload werden automatisch optimierte Versionen in verschiedenen Größen und Formaten erstellt.


Konfiguration

Sharp Integration

Sharp ist in der payload.config.ts eingebunden:

import sharp from 'sharp'

export default buildConfig({
  // ...
  sharp,
  // ...
})

Media Collection

Die Bildoptimierung ist in src/collections/Media.ts konfiguriert.


Image Sizes

WebP-Varianten

Name Breite Höhe Verwendung
thumbnail 150px 150px Admin-Übersichten, kleine Vorschauen
small 400px auto Cards, Avatare, Icons
medium 800px auto Blog-Vorschauen, Testimonials
large 1200px auto Hero-Sections, Vollbild
xlarge 1920px auto Full-HD Displays
2k 2560px auto Retina/HiDPI Displays
og 1200x630px fix Social Media / Open Graph

AVIF-Varianten (beste Kompression)

Name Breite Verwendung
medium_avif 800px Blog-Vorschauen (moderne Browser)
large_avif 1200px Hero-Sections (moderne Browser)
xlarge_avif 1920px Full-HD (moderne Browser)

Qualitätseinstellungen

Format Size Qualität
WebP thumbnail 80%
WebP small 80%
WebP medium 82%
WebP large, xlarge, 2k, og 85%
AVIF alle 70%

Die niedrigere AVIF-Qualität (70%) liefert bei gleicher visueller Qualität kleinere Dateien als WebP bei 85%.


Fit-Modi

Modus Beschreibung Verwendung
cover Füllt die Größe, schneidet überstehende Bereiche ab thumbnail, og
inside Passt das Bild ein, behält Seitenverhältnis alle anderen

withoutEnlargement

Alle Sizes außer thumbnail und og haben withoutEnlargement: true. Das verhindert, dass kleine Bilder künstlich vergrößert werden.


Fokuspunkt

Die Media Collection unterstützt Fokuspunkte (focalPoint: true). Damit können Redakteure den wichtigsten Bereich eines Bildes markieren, der beim Cropping erhalten bleibt.

Im Admin-Panel:

  1. Bild hochladen
  2. Auf das Bild klicken
  3. Fokuspunkt setzen

Die Fokuspunkt-Koordinaten werden in focal_x und focal_y gespeichert.


Zusätzliche Felder

Feld Typ Beschreibung
alt Text Alt-Text (Pflichtfeld)
caption Text Bildunterschrift
credit Text Fotograf/Copyright
tags Text[] Schlagwörter für Suche

API-Response

Beim Abruf eines Media-Dokuments werden alle Sizes zurückgegeben:

{
  "id": 1,
  "alt": "Beispielbild",
  "caption": "Eine Bildunterschrift",
  "credit": "Fotograf Name",
  "url": "/media/original.jpg",
  "width": 4000,
  "height": 3000,
  "mimeType": "image/jpeg",
  "filesize": 2500000,
  "focalX": 50,
  "focalY": 50,
  "sizes": {
    "thumbnail": {
      "url": "/media/original-150x150.webp",
      "width": 150,
      "height": 150,
      "mimeType": "image/webp",
      "filesize": 8500
    },
    "small": {
      "url": "/media/original-400x300.webp",
      "width": 400,
      "height": 300,
      "mimeType": "image/webp",
      "filesize": 25000
    },
    "medium": {
      "url": "/media/original-800x600.webp",
      "width": 800,
      "height": 600,
      "mimeType": "image/webp",
      "filesize": 65000
    },
    "large": {
      "url": "/media/original-1200x900.webp",
      "width": 1200,
      "height": 900,
      "mimeType": "image/webp",
      "filesize": 120000
    },
    "medium_avif": {
      "url": "/media/original-800x600.avif",
      "width": 800,
      "height": 600,
      "mimeType": "image/avif",
      "filesize": 35000
    }
    // ... weitere Sizes
  }
}

Frontend-Integration

Responsive Images mit srcset

function ResponsiveImage({ media }) {
  const { url, alt, sizes } = media

  return (
    <picture>
      {/* AVIF für moderne Browser */}
      <source
        type="image/avif"
        srcSet={`
          ${sizes.medium_avif?.url} 800w,
          ${sizes.large_avif?.url} 1200w,
          ${sizes.xlarge_avif?.url} 1920w
        `}
        sizes="(max-width: 800px) 100vw, 50vw"
      />
      {/* WebP Fallback */}
      <source
        type="image/webp"
        srcSet={`
          ${sizes.small?.url} 400w,
          ${sizes.medium?.url} 800w,
          ${sizes.large?.url} 1200w,
          ${sizes.xlarge?.url} 1920w,
          ${sizes['2k']?.url} 2560w
        `}
        sizes="(max-width: 800px) 100vw, 50vw"
      />
      {/* Original als Fallback */}
      <img
        src={url}
        alt={alt}
        loading="lazy"
      />
    </picture>
  )
}

Next.js Image Component

import Image from 'next/image'

function OptimizedImage({ media }) {
  return (
    <Image
      src={media.sizes.large?.url || media.url}
      alt={media.alt}
      width={media.sizes.large?.width || media.width}
      height={media.sizes.large?.height || media.height}
      placeholder="blur"
      blurDataURL={media.sizes.thumbnail?.url}
    />
  )
}

Thumbnail für Listen

function MediaThumbnail({ media }) {
  return (
    <img
      src={media.sizes.thumbnail?.url || media.url}
      alt={media.alt}
      width={150}
      height={150}
      loading="lazy"
    />
  )
}

Social Media / Open Graph

Die og-Size (1200x630px) ist optimiert für Social Media Sharing:

// In Next.js Metadata
export async function generateMetadata({ params }) {
  const page = await getPage(params.slug)

  return {
    openGraph: {
      images: [
        {
          url: page.featuredImage?.sizes?.og?.url,
          width: 1200,
          height: 630,
        },
      ],
    },
  }
}

Dateispeicherung

Alle Bildvarianten werden im /media-Verzeichnis gespeichert:

/media/
├── original.jpg           # Original
├── original-150x150.webp  # thumbnail
├── original-400x300.webp  # small
├── original-800x600.webp  # medium
├── original-800x600.avif  # medium_avif
├── original-1200x900.webp # large
├── original-1200x900.avif # large_avif
├── original-1920x1440.webp # xlarge
├── original-1920x1440.avif # xlarge_avif
├── original-2560x1920.webp # 2k
└── original-1200x630.webp  # og

Kompressionsvergleich

Typische Dateigrößen für ein 4000x3000px Foto:

Format/Size Dateigröße Ersparnis
Original JPEG 2.5 MB -
large (WebP) ~120 KB 95%
large (AVIF) ~70 KB 97%
medium (WebP) ~65 KB 97%
medium (AVIF) ~35 KB 99%
thumbnail (WebP) ~8 KB 99.7%

Browser-Kompatibilität

WebP

  • Chrome 17+
  • Firefox 65+
  • Safari 14+
  • Edge 18+

AVIF

  • Chrome 85+
  • Firefox 93+
  • Safari 16.4+
  • Edge 121+

Für ältere Browser wird das Original-Format (JPEG/PNG) als Fallback verwendet.


Datenbank-Tabellen

Die Migration 20251130_143000_media_optimization erstellt:

  • Spalten für alle Size-Varianten in media
  • Tabelle media_tags für Schlagwörter

Changelog

Version 1.0 (30.11.2025)

  • Sharp-Integration in payload.config.ts
  • 11 Image Sizes definiert (7 WebP + 3 AVIF + OG)
  • Fokuspunkt-Support aktiviert
  • Zusätzliche Felder: caption, credit, tags
  • Migration für Datenbank-Schema