perf: Produktbilder werden als AVIF ausgeliefert
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m43s

next/image lieferte bisher nur WebP (die Next.js-Vorgabe). Am Hero-Bild der
Startseite (wabenhain.com, 1920x1280) nachgemessen, mit genau den
Einstellungen, die Next.js selbst verwendet — WebP q75 gegen AVIF q47
(image-optimizer.js skaliert die Qualitaet mit 50/80) bei effort 3:

    Breite   WebP        AVIF
      640     21,2 kB     12,0 kB   -43 %
      828     30,2 kB     17,4 kB   -42 %
     1080     44,4 kB     26,5 kB   -40 %
     1920    105,0 kB     65,7 kB   -37 %

Auf einer Shop-Uebersicht mit einem Dutzend Kacheln ist das der groesste
einzelne Posten der Seite. Browser ohne AVIF-Unterstuetzung bekommen
unveraendert WebP, ganz alte das Original; die Auswahl trifft Next.js anhand
des Accept-Headers.

Die Kodierdauer spricht nicht dagegen: bei effort 3 lag AVIF in derselben
Messung durchgehend gleichauf oder schneller als WebP (1920 px: 60 ms gegen
122 ms). minimumCacheTTL steigt trotzdem von den voreingestellten vier Wochen
auf ein Jahr — nicht wegen der Kodierdauer, sondern weil hochgeladene Bilder
unveraenderlich sind: lib/uploads.ts legt jede Datei unter einem eigenen
Namen ab, ein ausgetauschtes Produktbild bekommt also eine neue URL. Ein
kurzes TTL wirft hier nur brauchbare Ergebnisse weg.

Dazu zwei ausdrueckliche Festschreibungen, die das bisherige Verhalten
dokumentieren statt es zu aendern:

- qualities: [75] entspricht der Vorgabe von Next.js 16, die andere Werte
  bereits ablehnt (gegen die laufende Seite geprueft: ?q=42 antwortet mit
  400). Ausgeschrieben, damit eine spaetere Erweiterung der Liste eine
  bewusste Entscheidung ist und nicht unbemerkt Kodier-Last je Wert oeffnet.
- dangerouslyAllowSVG: false entspricht ebenfalls der Vorgabe. Ausgeschrieben,
  weil ein SVG ein Dokument ist, das Skripte enthalten kann, und hier
  same-origin ausgeliefert wuerde.

tsc: 0 Fehler. vitest: 359/359 gruen. eslint: 0 Warnungen. next build: gruen.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5 committed 2026-09-20 03:12:44 +02:00
1 parent 73c070f11e
commit 7dd42e35bc
1 file changed
+37
+37
View File
@@ -25,6 +25,43 @@ const nextConfig: NextConfig = {
// werden."
serverExternalPackages: ["pdfkit", "ffmpeg-static"],
images: {
// AVIF vor WebP. Next.js liefert das erste Format, das der Browser laut
// Accept-Header unterstuetzt; Browser ohne AVIF bekommen unveraendert
// WebP, ganz alte das Original.
//
// Am Hero-Bild der Startseite nachgemessen (1920x1280), mit den
// Einstellungen aus next/dist/server/image-optimizer.js — WebP q75 gegen
// AVIF q47 (Next.js skaliert die Qualitaet mit 50/80) bei effort 3:
// 640 px -43 %, 828 px -42 %, 1080 px -40 %, 1920 px -37 %.
//
// Die Kodierdauer spricht nicht dagegen: bei effort 3 lag AVIF in
// derselben Messung gleichauf oder schneller als WebP (1920 px: 60 ms
// gegen 122 ms). Die frueher hier vermutete teure Erstkodierung gibt es
// in dieser Einstellung nicht.
formats: ["image/avif", "image/webp"],
// Ein Jahr statt der Next.js-Vorgabe von vier Wochen. Hochgeladene Bilder
// sind unveraenderlich: lib/uploads.ts legt jede Datei unter einem eigenen
// Namen ab, ein ausgetauschtes Produktbild bekommt also eine neue URL.
// Ein kurzes TTL wuerde hier nur brauchbare Ergebnisse wegwerfen.
minimumCacheTTL: 60 * 60 * 24 * 365,
// Entspricht der Vorgabe von Next.js 16, die andere Werte bereits ablehnt
// (gegen die laufende Seite geprueft: ?q=42 antwortet mit 400) — aendert
// das Verhalten also nicht. Ausgeschrieben, damit eine spaetere
// Erweiterung der Liste eine bewusste Entscheidung ist: jeder zusaetzlich
// erlaubte Wert oeffnet einen eigenen Cache-Eintrag und eine eigene
// Kodierung je Bild, von aussen ueber die URL ausloesbar.
qualities: [75],
// Ebenfalls die Vorgabe, ausdruecklich festgehalten: ein SVG ist ein
// Dokument, das Skripte enthalten kann — same-origin ausgeliefert waere
// das ein XSS-Vektor. Diese Zeile soll verhindern, dass der Schalter
// spaeter beilaeufig umgelegt wird.
dangerouslyAllowSVG: false,
},
// Turbopacks Dateisystem-Caches (.next/dev/cache & .next/cache/turbopack)
// kollidieren in diesem OneDrive-synchronisierten Arbeitsverzeichnis
// wiederholt mit der Cloud-Synchronisierung ("Failed to open database" /