Bildoptimierung: WebP + Lazy Loading + Caching #17

Closed
opened 2026-05-14 00:29:42 +02:00 by greggy · 1 comment
Owner

Problem

Bilder als PNG (unoptimiert), kein lazy loading, keine Cache-Headers in nginx.

Nutzen

Deutlich schnellere Ladezeit, besonders auf Mobile. Weniger Bandbreite.

Technische Umsetzung

  1. Alle Bilder nach WebP konvertieren (mit Fallback)
  2. loading=lazy auf alle img-Tags
  3. nginx Cache-Headers für statische Assets
  4. Masonry.js entfernen (wird nicht genutzt, spart 70KB)

Aufwand: Mittel | Risiko: Niedrig | Empfehlung: Sehr sinnvoll

## Problem Bilder als PNG (unoptimiert), kein lazy loading, keine Cache-Headers in nginx. ## Nutzen Deutlich schnellere Ladezeit, besonders auf Mobile. Weniger Bandbreite. ## Technische Umsetzung 1. Alle Bilder nach WebP konvertieren (mit Fallback) 2. loading=lazy auf alle img-Tags 3. nginx Cache-Headers für statische Assets 4. Masonry.js entfernen (wird nicht genutzt, spart 70KB) ## Aufwand: Mittel | Risiko: Niedrig | Empfehlung: Sehr sinnvoll
greggy added the
KI
label 2026-05-14 00:29:42 +02:00
Author
Owner

Spezifikation: Issue #17 – Bildoptimierung: WebP + Lazy Loading + Caching

Repo: greggy/landingpage-haus-schleusingen
Komplexität: M (Medium)
Geschätzter Aufwand: 2–3h
Risiko: Niedrig


1. Zusammenfassung

Die Landingpage lädt aktuell ~21 MB an unoptimierten Bildern (PNG/JPG). Es gibt kein Lazy Loading und nginx sendet keine Cache-Headers. Masonry.js (24 KB) wird eingebunden aber nie initialisiert – kann entfernt werden.

2. Ist-Zustand

Bilder (21 MB in /bilder/)

  • 34 Bilddateien in 3 Formaten: PNG (12), JPG (13), JPEG (4), plus 5 -small Varianten als PNG
  • Größte Einzeldateien: Kinderzimmer 3.jpg (2,8 MB), Kinderzimmer 2.jpg (2,5 MB), Außenansicht-2.png (2,5 MB)
  • ** -small Varianten** existieren für Thumbnails, sind aber oft noch PNG und nicht signifikant kleiner
  • Fehlende Datei: data-img="bilder/bad3.jpg" referenziert aber Datei heißt Bad-3.jpeg → 404 bei Lightbox-Click!
  • Fehlende Datei: data-img="bilder/WhatsApp Image 2026-03-30 at 07.50.42 (2).jpeg" und src="bilder/WhatsApp Image 2026-03-30 at 07.50.42 (2).jpeg" → Datei existiert nicht im Repo → 404!

HTML (haus-schleusingen.html)

  • 30 <img> Tags, davon haben keines ein loading="lazy" Attribut
  • Hero-Bild wird als CSS background-image geladen (kein <img> Tag)
  • Galerie nutzt CSS Columns (.masonry-grid mit column-count), kein JS Masonry

JavaScript

  • js/masonry.pkgd.min.js (24 KB) wird nicht geladen/gelinkt im HTML (kein <script> Tag!) – Datei existiert nur im Repo, wird also nicht mal ausgeliefert. Kann einfach gelöscht werden.
  • js/haus-schleusingen.js nutzt jQuery für Animationen, Lightbox, Accordion – kein Masonry-Aufruf

nginx (nginx.conf)

  • Minimale Konfiguration, keine Cache-Headers für statische Assets
  • Kein Gzip aktiviert
  • Kein Brotli

Dockerfile

  • Present, static build mit nginx

3. Teilaufgaben

3.1 Bilder nach WebP konvertieren

Priorität: Hoch | Aufwand: 30 Min

  • Alle 34 Bilder nach WebP konvertieren mit cwebp -q 80 (Qualität 80)
  • Erwartete Einsparung: 60–80% der Dateigröße (21 MB → ~4–6 MB)
  • Originale PNG/JPG beibehalten für Fallback
  • -small Varianten ebenfalls konvertieren

Konvertierungs-Script:

#!/bin/bash
find bilder/ -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" \) | while read f; do
  webp="${f%.*}.webp"
  cwebp -q 80 "$f" -o "$webp" 2>/dev/null
done

3.2 HTML: WebP mit Fallback

Priorität: Hoch | Aufwand: 30 Min

Für jedes <img> Tag ein <picture> Element erstellen:

<picture>
  <source srcset="bilder/wohnzimmer2-small.webp" type="image/webp">
  <img src="bilder/wohnzimmer2-small.png" alt="Wohnzimmer" loading="lazy">
</picture>
  • Ausnahme: Hero-CSS-Background → per JS/Modernizr WebP-Support prüfen oder per CSS image-set() oder per <picture> im Hero umsetzen
  • 30 <img> Tags müssen konvertiert werden
  • data-img Attribute für Lightbox auf .webp aktualisieren (mit Fallback-Logik im JS)

3.3 Lazy Loading

Priorität: Hoch | Aufwand: 15 Min

  • loading="lazy" auf alle <img> Tags außer dem Hero-Intro-Bild (above the fold)
  • Hero-Background bleibt eagerly loaded
  • Galerie-Thumbnails und Grundriss-Bilder werden lazy

3.4 Masonry.js entfernen

Priorität: Mittel | Aufwand: 5 Min

  • Datei js/masonry.pkgd.min.js löschen (24 KB)
  • Wird ohnehin nicht im HTML referenziert, also kein Impact
  • CSS .masonry-grid bleibt bestehen (reines CSS Columns Layout)

3.5 nginx Cache-Headers

Priorität: Hoch | Aufwand: 15 Min

server {
    listen 80;
    server_name localhost;

    root /usr/share/nginx/html;
    index haus-schleusingen.html;

    # Gzip aktivieren
    gzip on;
    gzip_types text/css application/javascript image/svg+xml;
    gzip_min_length 256;

    location / {
        try_files $uri $uri/ /haus-schleusingen.html;
    }

    # Lange Cache-Dauer für Bilder und statische Assets
    location ~* \.(jpg|jpeg|png|webp|gif|ico|svg|css|js|woff2?)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
}

3.6 Defekte Referenzen reparieren

Priorität: Hoch | Aufwand: 10 Min

  • data-img="bilder/bad3.jpg" → korrigieren zu data-img="bilder/Bad-3.jpeg"
  • data-img="bilder/WhatsApp Image ..." und src="bilder/WhatsApp Image ..." → prüfen ob Datei existiert, ggf. entfernen oder korrigieren

4. Akzeptanzkriterien

  • Alle Bilder als WebP verfügbar (mit Original-Fallback)
  • Alle <img> Tags nutzen <picture> mit WebP-Source
  • loading="lazy" auf allen below-the-fold Bildern
  • js/masonry.pkgd.min.js gelöscht
  • nginx sendet Cache-Header (30d) für statische Assets
  • Gzip in nginx aktiviert
  • Defekte Bildreferenzen (bad3.jpg, WhatsApp Image) repariert
  • Gesamte Bildgröße reduziert um mind. 60%
  • Lightbox funktioniert weiterhin mit WebP
  • Hero-Bild lädt weiterhin korrekt (above the fold)

5. Edge Cases

  • Browser ohne WebP-Support: Alte Safari-Versionen → Fallback über <picture> sichergestellt
  • Lightbox data-img: Muss sowohl WebP als auch Original-Pfad handhaben – am besten im JS den <source> srcset abfragen oder separate data-img-webp Attribute einführen
  • Hero-CSS-Background: Kein <picture> möglich → Lösung: per Modernizr/CSS Feature Query oder einfach das WebP direkt nutzen (95%+ Browser-Support) oder image-set() nutzen
  • Dateinamen mit Leerzeichen: Viele Dateien haben Leerzeichen → im Script korrekt quoten
  • Docker Build: WebP-Dateien müssen im Docker-Image landen – ggf. .dockerignore prüfen

6. Dateiänderungen

Datei Aktion
bilder/*.png/jpg/jpeg WebP-Versionen erstellen
haus-schleusingen.html <picture> Tags, loading="lazy", defekte Refs reparieren
nginx.conf Cache-Headers, Gzip
js/masonry.pkgd.min.js Löschen
js/haus-schleusingen.js Lightbox ggf. für WebP anpassen

7. Abhängigkeiten

  • cwebp CLI-Tool (Google libwebp) zum Konvertieren
  • Keine neuen npm/pip-Pakete nötig

8. Sicherheitsrelevante Aspekte

  • Keine sicherheitsrelevanten Änderungen
  • Cache-Header immutable ist sicher für statische Assets
  • Keine externen Dependencies hinzugefügt

9. Rollback-Strategie

  • Originale Bilder bleiben erhalten (WebP ist zusätzlich)
  • HTML-Änderungen über Git revertbar
  • nginx-Änderungen über Git revertbar
  • Kein Datenverlust-Risiko

Nächster Schritt: Übergabe an Implementierungs-Agent (Phase 2)

# Spezifikation: Issue #17 – Bildoptimierung: WebP + Lazy Loading + Caching **Repo:** `greggy/landingpage-haus-schleusingen` **Komplexität:** M (Medium) **Geschätzter Aufwand:** 2–3h **Risiko:** Niedrig --- ## 1. Zusammenfassung Die Landingpage lädt aktuell ~21 MB an unoptimierten Bildern (PNG/JPG). Es gibt kein Lazy Loading und nginx sendet keine Cache-Headers. Masonry.js (24 KB) wird eingebunden aber nie initialisiert – kann entfernt werden. ## 2. Ist-Zustand ### Bilder (21 MB in `/bilder/`) - **34 Bilddateien** in 3 Formaten: PNG (12), JPG (13), JPEG (4), plus 5 `-small` Varianten als PNG - Größte Einzeldateien: `Kinderzimmer 3.jpg` (2,8 MB), `Kinderzimmer 2.jpg` (2,5 MB), `Außenansicht-2.png` (2,5 MB) - ** `-small` Varianten** existieren für Thumbnails, sind aber oft noch PNG und nicht signifikant kleiner - **Fehlende Datei:** `data-img="bilder/bad3.jpg"` referenziert aber Datei heißt `Bad-3.jpeg` → 404 bei Lightbox-Click! - **Fehlende Datei:** `data-img="bilder/WhatsApp Image 2026-03-30 at 07.50.42 (2).jpeg"` und `src="bilder/WhatsApp Image 2026-03-30 at 07.50.42 (2).jpeg"` → Datei existiert nicht im Repo → 404! ### HTML (`haus-schleusingen.html`) - **30 `<img>` Tags**, davon haben **keines** ein `loading="lazy"` Attribut - **Hero-Bild** wird als CSS `background-image` geladen (kein `<img>` Tag) - Galerie nutzt CSS Columns (`.masonry-grid` mit `column-count`), **kein JS Masonry** ### JavaScript - `js/masonry.pkgd.min.js` (24 KB) wird nicht geladen/gelinkt im HTML (kein `<script>` Tag!) – Datei existiert nur im Repo, wird also nicht mal ausgeliefert. **Kann einfach gelöscht werden.** - `js/haus-schleusingen.js` nutzt jQuery für Animationen, Lightbox, Accordion – kein Masonry-Aufruf ### nginx (`nginx.conf`) - Minimale Konfiguration, **keine Cache-Headers** für statische Assets - Kein Gzip aktiviert - Kein Brotli ### Dockerfile - Present, static build mit nginx ## 3. Teilaufgaben ### 3.1 Bilder nach WebP konvertieren **Priorität:** Hoch | **Aufwand:** 30 Min - **Alle 34 Bilder** nach WebP konvertieren mit `cwebp -q 80` (Qualität 80) - Erwartete Einsparung: 60–80% der Dateigröße (21 MB → ~4–6 MB) - Originale PNG/JPG beibehalten für Fallback - `-small` Varianten ebenfalls konvertieren **Konvertierungs-Script:** ```bash #!/bin/bash find bilder/ -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" \) | while read f; do webp="${f%.*}.webp" cwebp -q 80 "$f" -o "$webp" 2>/dev/null done ``` ### 3.2 HTML: WebP mit Fallback **Priorität:** Hoch | **Aufwand:** 30 Min Für jedes `<img>` Tag ein `<picture>` Element erstellen: ```html <picture> <source srcset="bilder/wohnzimmer2-small.webp" type="image/webp"> <img src="bilder/wohnzimmer2-small.png" alt="Wohnzimmer" loading="lazy"> </picture> ``` - **Ausnahme:** Hero-CSS-Background → per JS/Modernizr WebP-Support prüfen oder per CSS `image-set()` oder per `<picture>` im Hero umsetzen - **30 `<img>` Tags** müssen konvertiert werden - `data-img` Attribute für Lightbox auf `.webp` aktualisieren (mit Fallback-Logik im JS) ### 3.3 Lazy Loading **Priorität:** Hoch | **Aufwand:** 15 Min - `loading="lazy"` auf alle `<img>` Tags **außer** dem Hero-Intro-Bild (above the fold) - Hero-Background bleibt eagerly loaded - Galerie-Thumbnails und Grundriss-Bilder werden lazy ### 3.4 Masonry.js entfernen **Priorität:** Mittel | **Aufwand:** 5 Min - Datei `js/masonry.pkgd.min.js` löschen (24 KB) - Wird ohnehin nicht im HTML referenziert, also kein Impact - CSS `.masonry-grid` bleibt bestehen (reines CSS Columns Layout) ### 3.5 nginx Cache-Headers **Priorität:** Hoch | **Aufwand:** 15 Min ```nginx server { listen 80; server_name localhost; root /usr/share/nginx/html; index haus-schleusingen.html; # Gzip aktivieren gzip on; gzip_types text/css application/javascript image/svg+xml; gzip_min_length 256; location / { try_files $uri $uri/ /haus-schleusingen.html; } # Lange Cache-Dauer für Bilder und statische Assets location ~* \.(jpg|jpeg|png|webp|gif|ico|svg|css|js|woff2?)$ { expires 30d; add_header Cache-Control "public, immutable"; access_log off; } } ``` ### 3.6 Defekte Referenzen reparieren **Priorität:** Hoch | **Aufwand:** 10 Min - `data-img="bilder/bad3.jpg"` → korrigieren zu `data-img="bilder/Bad-3.jpeg"` - `data-img="bilder/WhatsApp Image ..."` und `src="bilder/WhatsApp Image ..."` → prüfen ob Datei existiert, ggf. entfernen oder korrigieren ## 4. Akzeptanzkriterien - [ ] Alle Bilder als WebP verfügbar (mit Original-Fallback) - [ ] Alle `<img>` Tags nutzen `<picture>` mit WebP-Source - [ ] `loading="lazy"` auf allen below-the-fold Bildern - [ ] `js/masonry.pkgd.min.js` gelöscht - [ ] nginx sendet Cache-Header (30d) für statische Assets - [ ] Gzip in nginx aktiviert - [ ] Defekte Bildreferenzen (bad3.jpg, WhatsApp Image) repariert - [ ] Gesamte Bildgröße reduziert um mind. 60% - [ ] Lightbox funktioniert weiterhin mit WebP - [ ] Hero-Bild lädt weiterhin korrekt (above the fold) ## 5. Edge Cases - **Browser ohne WebP-Support:** Alte Safari-Versionen → Fallback über `<picture>` sichergestellt - **Lightbox `data-img`:** Muss sowohl WebP als auch Original-Pfad handhaben – am besten im JS den `<source>` srcset abfragen oder separate `data-img-webp` Attribute einführen - **Hero-CSS-Background:** Kein `<picture>` möglich → Lösung: per Modernizr/CSS Feature Query oder einfach das WebP direkt nutzen (95%+ Browser-Support) oder `image-set()` nutzen - **Dateinamen mit Leerzeichen:** Viele Dateien haben Leerzeichen → im Script korrekt quoten - **Docker Build:** WebP-Dateien müssen im Docker-Image landen – ggf. `.dockerignore` prüfen ## 6. Dateiänderungen | Datei | Aktion | |---|---| | `bilder/*.png/jpg/jpeg` | WebP-Versionen erstellen | | `haus-schleusingen.html` | `<picture>` Tags, `loading="lazy"`, defekte Refs reparieren | | `nginx.conf` | Cache-Headers, Gzip | | `js/masonry.pkgd.min.js` | **Löschen** | | `js/haus-schleusingen.js` | Lightbox ggf. für WebP anpassen | ## 7. Abhängigkeiten - `cwebp` CLI-Tool (Google libwebp) zum Konvertieren - Keine neuen npm/pip-Pakete nötig ## 8. Sicherheitsrelevante Aspekte - Keine sicherheitsrelevanten Änderungen - Cache-Header `immutable` ist sicher für statische Assets - Keine externen Dependencies hinzugefügt ## 9. Rollback-Strategie - Originale Bilder bleiben erhalten (WebP ist zusätzlich) - HTML-Änderungen über Git revertbar - nginx-Änderungen über Git revertbar - Kein Datenverlust-Risiko --- **Nächster Schritt:** Übergabe an Implementierungs-Agent (Phase 2)
greggy added the
ReadyForDev
label 2026-05-14 00:59:47 +02:00
greggy added the
Implementing
InReview
ReadyForMerge
labels 2026-05-14 01:17:08 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: greggy/landingpage-haus-schleusingen#17
No description provided.