Bilder mit Next.js
next/image funktioniert bei gooddeploy ohne Einstellungen: Bilder werden beim ersten Aufruf verkleinert, ins passende Format umgerechnet (AVIF oder WebP, je nach Browser) und danach aus dem Cache ausgeliefert. Hier steht, was dabei passiert und worauf du achten solltest.
Was du tun musst
Nichts. Nutze <Image> aus next/image wie gewohnt, mit Bildern aus public/, mit statischen Importen (import foto from "./foto.jpg") oder mit Bildern von anderen Servern, die du in next.config unter images.remotePatterns freigibst. gooddeploy installiert sharp für die Umrechnung selbst, wenn es nicht in deinem Projekt steht.
Formate legst du wie gewohnt in next.config fest, zum Beispiel:
images: { formats: ["image/avif", "image/webp"] },
Erster Aufruf und Cache
- Beim ersten Aufruf eines Bildes in einer Größe und einem Format rechnet die App es um. Das dauert je Bild etwa eine halbe Sekunde, AVIF länger als WebP. Kommen viele neue Bilder gleichzeitig (eine Galerie mit 30 Bildern), stellt gooddeploy sie in eine Warteschlange: Die ersten erscheinen sofort, die letzten nach einigen Sekunden, aber keines fehlt.
- Danach kommen die Bilder aus dem Cache, in wenigen Millisekunden. Der Cache gilt für eine Umgebung deines Projekts auf einem Server: Alle Instanzen dort teilen ihn, und er bleibt bei neuen Deployments und Neustarts erhalten. Preview und Live haben aus Sicherheitsgründen getrennte Caches; nach einem Promote rechnet Live jedes Bild einmal neu.
- Ändert sich eine Datei in
public/, rechnet das neue Deployment nur die Bilder dieser Datei neu. gooddeploy erkennt Änderungen am Inhalt, nicht am Datum: Ersetzt dupublic/team.jpgdurch ein anderes Foto mit gleichem Namen, siehst du nach dem Deployment das neue Foto, alle anderen Bilder kommen weiter aus dem Cache. Kommt ein Bild dazu oder ändert sich nurrobots.txt, bleiben alle fertigen Bilder erhalten. Bilder aus statischen Importen und entfernte Bilder bleiben ebenfalls im Cache. - Während eines Promotes liefert die bisherige Version bis zu ihrem Ende ihre eigenen Bilder aus, die neue Version ihre. So passen Seite und Bilder immer zusammen.
- Erlaubst du in
images.localPatternsAdressen mit Query (z. B./foto.jpg?v=2), kann gooddeploy nicht jede Adresse einer Datei kennen. Dann beginnt ein Deployment mit Änderung inpublic/mit einem frischen Cache, und alle Bilder werden einmal neu gerechnet. Das gilt auch für sehr neue Next.js-Versionen, deren Cache gooddeploy noch nicht geprüft hat. - Bilder aus eigenen Route-Handlern (z. B.
/api/foto?id=1, freigegeben überimages.localPatterns) erkennt gooddeploy nicht am Inhalt. Ändert ein Deployment nur, was so eine Route liefert, kommt bis zum Ablauf vonimages.minimumCacheTTL(Standard 4 Stunden) noch das alte Bild. Gib geänderten Bildern eine neue Adresse (z. B.?v=2) oder setzeminimumCacheTTLkleiner. - Ein Bild, das noch niemand aufgerufen hat, wird nicht vorab gerechnet.
Im Header X-Nextjs-Cache siehst du, woher ein Bild kam: MISS (gerade gerechnet), HIT (aus dem Cache), STALE (aus dem Cache, wird im Hintergrund erneuert).
Cache im Browser
Die Header setzt Next.js, gooddeploy ändert sie nicht:
| Was | Cache-Control |
|---|---|
Bilder aus public/ und von anderen Servern (images.remotePatterns) | public, max-age=<minimumCacheTTL>, must-revalidate (Standard 4 Stunden) |
statische Importe (/_next/static/media/…) | public, max-age=315360000, immutable |
Skripte und Styles (/_next/static/…) | public, max-age=31536000, immutable |
Vary: Accept sorgt dafür, dass jeder Browser das Format bekommt, das er kann. Willst du, dass Besucher geänderte Bilder aus public/ schneller sehen, setze images.minimumCacheTTL kleiner oder gib geänderten Bildern einen neuen Dateinamen.
Tipps
- Lade nur Bilder sofort, die oben auf der Seite stehen (
prioritybzw.loading="eager"). Der Rest lädt erst beim Scrollen; das verteilt die Umrechnung beim ersten Besuch. - Große Originale (mehrere MB) kosten bei der ersten Umrechnung am meisten Zeit. Verkleinere sie vor dem Commit auf die größte Breite, die du brauchst (meist 2400 px).
- Mit
unoptimizedan einem<Image>oderimages.unoptimized: trueinnext.configschaltest du die Umrechnung ab; dann kommt die Originaldatei.
Ohne sharp
Fehlt sharp und lässt es sich nicht nachinstallieren (zum Beispiel bei manchen bun-Projekten), warnt das Build-Log: „sharp nicht installiert“. Wie sich next/image dann verhält, hängt von der Next.js-Version ab und ist bei uns noch nicht geprüft (kommt später). Nimm sharp deshalb als Abhängigkeit in package.json auf.
Was noch fehlt
- Ein gemeinsamer Cache über alle Server: Läuft deine Seite auf mehreren Servern (Live auf zwei Servern), rechnet jeder Server ein Bild einmal (kommt später).
- Ein CDN vor den Bildern kommt später.