Next.js Bildoptimierung: Der vollständige Leitfaden zur Image-Komponente

Lighthouse-Score: 62 Punkte.
Zwei Wochen Arbeit in einem Next.js-Projekt – und die Performance-Bewertung gerade mal ausreichend. Unter Performance der größte Brocken: LCP (Largest Contentful Paint) bei 4,8 Sekunden, fast alles durch Bilder.
Damals war ich ratlos. Next.js sollte doch von Haus aus optimieren? Im Code: Hero-Bild auf der Startseite noch mit barem <img>, in der Shop-Liste Dutzende Produktbilder als 3–4-MB-Originale vom Server.
Erst später wurde klar: Next.js ist stark, aber Bildoptimierung braucht die Image-Komponente aktiv. Richtig eingesetzt, oft 60–80 % weniger Bildvolumen und LCP unter zwei Sekunden.
Viele scheitern trotzdem: Remote-Bilder mit „Un-configured Host“, springende Layouts, unübersichtliche Optionen. Dieser Artikel bündelt Stolpersteine und Lösungen – von null bis zur sauberen Next.js Image-Nutzung.
Warum die Next.js Image-Komponente?
Drei Fallen des normalen img-Tags
Ein <img src="xxx"> reicht doch? Beim Performance-Test zeigte sich das Gegenteil.
Erste Falle: kein Format-Tuning, verschwendete Bandbreite
Ein normales img lädt, was Sie liefern: 3-MB-PNG bleibt 3-MB. Moderne Browser unterstützen WebP (~30 % kleiner als JPEG) und AVIF (noch ~40 %). Das img-Tag wählt das nicht – es lädt nur die angegebene Datei.
Zweite Falle: eine Datei für alle Bildschirme
Besonders mobil: 2000×1500 hochgeladen, Viewport 375 px breit – trotzdem das Vollbild, vom Browser verkleinert. Langsam und teuer.
Dritte Falle: Layout-Verschiebung (CLS)
Seite lädt, Sie wollen klicken – ein Bild poppt rein, alles rutscht, falscher Klick. Das ist CLS (Cumulative Layout Shift), ein Core Web Vitals-Wert und SEO-Faktor.
Automatische Optimierung der Image-Komponente
Die Next.js Image-Komponente ist mehr als ein img-Wrapper – ein komplettes Optimierungspaket.
Automatische Formatauswahl
Anhand des Accept-Headers: AVIF wenn möglich, sonst WebP, sonst Original. Ohne Extra-Code.
Im Test: 500-KB-JPEG → WebP ~180 KB, AVIF ~120 KB. Bei vielen Bildern summiert sich das.
Responsive Loading
Je Viewport passende Varianten (srcset-Logik automatisch). Mobil ~375 px, Desktop ~1920 px – ohne manuelles srcset-Basteln.
Lazy Loading
Standard: nur Bilder im Viewport laden. Weniger Daten beim ersten Paint, schnellerer Start.
In der Praxis: 60–80 % weniger Bildvolumen, LCP unter 2,5 s, CLS nahe null – keine Theorie, sondern Messwerte aus echten Projekten.
Grundlagen: lokale vs. Remote-Bilder
Verwirrend am Anfang: manche Bilder funktionieren sofort, andere werfen Fehler. Unterschied: lokal vs. extern.
Lokale Bilder: der einfachste Fall
Dateien im Projekt – zwei gängige Wege.
Variante 1: import (empfohlen)
import heroImage from '/public/images/hero.jpg'
import Image from 'next/image'
export default function Home() {
return (
<Image
src={heroImage}
alt="Hero image"
/>
)
}
Beim Build liest Next.js Breite und Höhe aus – oft ohne manuelles width/height. Für lokale Assets die bevorzugte Variante.
Variante 2: Pfad direkt
<Image
src="/images/hero.jpg"
width={1920}
height={1080}
alt="Hero image"
/>
Unter public/ mit Pfad – dann width und height Pflicht, sonst Fehler.
Remote-Bilder: die häufigste Stolperfalle
Externe URLs (z. B. Cloud Storage).
Typischer Fehler: „Un-configured Host“
<Image
src="https://images.unsplash.com/photo-123456"
width={800}
height={600}
alt="Sample image"
/>
Ohne Config meist:
Error: Invalid src prop (https://images.unsplash.com/photo-123456) on `next/image`,
hostname "images.unsplash.com" is not configured under images in your `next.config.js`
Next.js will verhindern, dass beliebige URLs über Ihren Optimierungs-Endpunkt laufen. Erlaubte Hosts müssen explizit stehen.
Richtig: remotePatterns
In next.config.js (Next.js 14+ empfohlen):
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.unsplash.com',
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
},
],
},
}
module.exports = nextConfig
Bedeutung:
protocol: https oder httphostname: exakte Domainport: meist leerpathname:/**oder eingeschränkter Pfad
Nach Änderung: Dev-Server neu starten. Einmal Config geändert, Server nicht neu gestartet – halbe Stunde Debug umsonst.
Legacy: domains (nicht empfohlen)
module.exports = {
images: {
domains: ['images.unsplash.com', 's3.amazonaws.com'],
},
}
In Next.js 14+ veraltet; remotePatterns ist sicherer (Pfad einschränkbar).
Warum width und height Pflicht sind
Außer per import müssen width und height gesetzt werden – gegen CLS.
Der Browser braucht Platzreservierung vor dem Download. Ohne Maße: Layout springt nach dem Laden.
Responsive Breite? Dafür gibt es fill (siehe unten).
Layout-Verschiebung (CLS) vermeiden
Springende Seiten nerven. Auf einer News-Site die häufigste Beschwerde: „Wollte den Titel klicken – Bild kam, Klick landete auf der Werbung.“
Was CLS ist und warum es zählt
CLS = kumulative Verschiebung während des Ladens. Google Core Web Vitals, SEO-relevant. Schlecht ab 0,1; gut darunter. Viele Bilder ohne Platzhalter → hoher CLS.
Wie Image CLS verhindert
Kern: Platz im Layout reservieren.
Mit width und height reserviert der Browser den Bereich vor dem Download – kein Sprung.
<Image
src="/product.jpg"
width={400}
height={300}
alt="Product image"
/>
400×300 Platzhalter, dann Bild – CLS oft null.
Bei fluidem Layout reicht feste Pixel nicht – dann fill.
Responsive: fill
Bild füllt den Parent; Größe per CSS.
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<Image
src="/hero.jpg"
fill
style={{ objectFit: 'cover' }}
alt="Hero image"
/>
</div>
Wichtig:
- Parent:
position: relative - Parent: feste Höhe (nicht nur
height: auto) objectFit:cover(füllen, ggf. crop) odercontain(ganzes Bild, evtl. Ränder)
Mit bekannter Parent-Höhe bleibt CLS kontrollierbar.
sizes: welche Auflösung laden?
Mit fill brauchen Sie sizes, sonst wählt Next.js die falsche Variante.
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<Image
src="/hero.jpg"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
style={{ objectFit: 'cover' }}
alt="Hero image"
/>
</div>
Bedeutung:
- ≤768 px: 100 % Viewport-Breite
- 768–1200 px: 50 % Viewport
-
1200 px: 33 % Viewport
Next.js erzeugt passende Varianten; das Gerät lädt die passende – weniger Daten, schneller.
Praxis: typische Layouts
Hero (volle Breite, Above-the-fold)
<div style={{ position: 'relative', width: '100%', height: '60vh' }}>
<Image
src="/hero.jpg"
fill
priority
sizes="100vw"
style={{ objectFit: 'cover' }}
alt="Hero image"
/>
</div>
priority für sofortiges Laden; sizes="100vw" = volle Viewport-Breite.
Artikel-Thumbnail (fest)
<Image
src={post.thumbnail}
width={300}
height={200}
alt={post.title}
/>
Produktgitter (responsive)
<div style={{ position: 'relative', width: '100%', paddingBottom: '100%' }}>
<Image
src={product.image}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
style={{ objectFit: 'cover' }}
alt={product.name}
/>
</div>
paddingBottom: '100%' = quadratischer 1:1-Container; mobil 1 Spalte, Tablet 2, Desktop 3.
Performance: zentrale Props
priority: kritische Above-the-fold-Bilder
Standard: Lazy Load. Hero und Logo sollen sofort kommen – sonst leerer Bereich.
<Image
src="/hero.jpg"
width={1920}
height={1080}
priority
alt="Hero image"
/>
Mit priority: kein Lazy Load, preload im <head>, besserer LCP. Einmal Hero mit priority: LCP von 3,8 s auf 2,1 s.
Wann priority? Hero, großes Logo, Artikel-Header, alles was LCP sein kann.
Nicht auf alle 20 Bilder – parallele Downloads bremsen eher.
Next.js 16 (RC)
priority wird zu preload:
<Image
src="/hero.jpg"
width={1920}
height={1080}
preload
alt="Hero image"
/>
Alternativ:
<Image
src="/hero.jpg"
width={1920}
height={1080}
loading="eager"
fetchPriority="high"
alt="Hero image"
/>
loading: Lade-Strategie
lazy(Default): erst im Viewporteager: sofort
Meist reicht lazy; Above-the-fold mit eager oder priority.
// Unten auf der Seite – lazy (Default)
<Image src="/related-1.jpg" width={300} height={200} alt="Related post" />
// Hauptinhalt oben – eager
<Image src="/main-content.jpg" width={800} height={600} loading="eager" alt="Main content" />
quality: Qualität vs. Größe
1–100, Default 75.
<Image
src="/product.jpg"
width={800}
height={600}
quality={90}
alt="Product image"
/>
Faustregeln:
- Hero / wichtig:
quality={90} - Standard:
75 - Thumbnails / Hintergrund:
60
90 → 75: oft ~30 % kleiner, kaum sichtbar. 75 → 60: noch ~20 %, auf normalen Displays ok.
Next.js 16: quality kann Pflicht werden (Missbrauch über URL-Parameter). Beim Upgrade jedes Image mit quality versehen.
WebP vs. AVIF
Automatisch per Accept: AVIF > WebP > Original. AVIF ~30–40 % kleiner als WebP; Chrome 85+, Firefox 93+, Safari 16+.
Kombinierte Beispiele
Hero (priority, hohe Qualität)
<div style={{ position: 'relative', width: '100%', height: '60vh' }}>
<Image
src="/hero.jpg"
fill
priority
quality={90}
sizes="100vw"
style={{ objectFit: 'cover' }}
alt="Welcome to our site"
/>
</div>
Listen-Thumbnails
{posts.map(post => (
<Image
key={post.id}
src={post.thumbnail}
width={300}
height={200}
quality={75}
alt={post.title}
/>
))}
Footer-Icons
<Image
src="/footer-icon.png"
width={40}
height={40}
quality={60}
alt="Footer icon"
/>
Häufige Fehler und Fixes
Fehler 1: Un-configured Host
Error: Invalid src prop (https://example.com/image.jpg) on `next/image`,
hostname "example.com" is not configured under images in your `next.config.js`
Ursache: externe URL ohne remotePatterns.
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
port: '',
pathname: '/**',
},
],
},
}
Hinweise: Dev-Server neu starten; hostname exakt, kein *.example.com; mehrere Hosts = mehrere Einträge.
Fehler 2: hoher CLS
Symptom: Inhalte springen beim Bildladen.
Ursachen: fehlende width/height, oder fill ohne Parent-Höhe.
// ❌
<Image src="/product.jpg" alt="Product" />
// ✅
<Image src="/product.jpg" width={400} height={300} alt="Product" />
// ❌ Parent ohne Höhe
<div style={{ position: 'relative', width: '100%' }}>
<Image src="/hero.jpg" fill alt="Hero" />
</div>
// ✅
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<Image src="/hero.jpg" fill alt="Hero" />
</div>
Fehler 3: unscharf oder zu groß auf Mobile
Oft fehlendes sizes → Default 100vw, obwohl das Bild nur halb so breit ist.
<Image
src="/product.jpg"
width={400}
height={300}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
alt="Product"
/>
Feste Thumbnail-Größe: nur width/height, kein sizes nötig.
Fehler 4: veraltete APIs
domains → remotePatterns (siehe oben).
onLoadingComplete → onLoad
// ❌
<Image
src="/image.jpg"
width={400}
height={300}
onLoadingComplete={() => console.log('loaded')}
alt="Image"
/>
// ✅
<Image
src="/image.jpg"
width={400}
height={300}
onLoad={() => console.log('loaded')}
alt="Image"
/>
Next.js 16: priority → preload (siehe oben).
Kurz-Checkliste
- Remote:
remotePatterns? - Config-Änderung: Server neu gestartet?
width/heightoder Parent-Höhe beifill?fill: Parentrelative+ feste Höhe?- Responsive: sinnvolles
sizes? - Keine veralteten APIs (
domains,onLoadingComplete)?
Fortgeschritten: Best Practices
placeholder
blur (lokal per import)
import Image from 'next/image'
import heroImage from '/public/hero.jpg'
export default function Hero() {
return (
<Image
src={heroImage}
placeholder="blur"
alt="Hero image"
/>
)
}
Next.js erzeugt ein kleines Base64-Vorschaubild – bekannt von Instagram/Medium.
Remote mit blurDataURL
<Image
src="https://example.com/image.jpg"
width={800}
height={600}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
alt="Remote image"
/>
Tools wie blurred.dev oder sharp auf dem Server.
empty: explizit leerer Platzhalter (Default).
CDN / Custom Loader
// next.config.js
module.exports = {
images: {
loader: 'cloudinary',
path: 'https://res.cloudinary.com/your-cloud-name/',
},
}
Oder custom:
module.exports = {
images: {
loader: 'custom',
loaderFile: './my-loader.js',
},
}
// my-loader.js
export default function myLoader({ src, width, quality }) {
return `https://cdn.example.com/${src}?w=${width}&q=${quality || 75}`
}
Traffic läuft über Ihr CDN statt den Next.js-Optimierer – sinnvoll bei hohem Volumen.
Responsive: sizes + CSS
<div className="image-container">
<Image
src="/product.jpg"
width={1200}
height={800}
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
style={{
width: '100%',
height: 'auto',
}}
alt="Product image"
/>
</div>
.image-container {
width: 100%;
}
@media (min-width: 640px) {
.image-container {
width: 50%;
}
}
@media (min-width: 1024px) {
.image-container {
width: 33.333%;
}
}
sizes und Media Queries sollten zusammenpassen.
Monitoring
Chrome DevTools → Network → Img: Größe, Zeit, Format (optimierte URLs oft mit ?w=…&q=…).
Lighthouse: LCP < 2,5 s, CLS < 0,1; Hinweise zu unoptimierten Bildern.
Nach Optimierung oft von ~60 auf 90+ Punkte.
Produktion: Google Search Console oder Vercel Analytics für Core Web Vitals.
Fazit
Kernprobleme: langsame Bilder, Config-Fehler, Layout-Sprünge.
Mit Image typischerweise:
- 60–80 % weniger Volumen (WebP/AVIF)
- LCP < 2,5 s (
prioritygezielt) - CLS nahe null (
width/heightoderfill+ Parent)
Merken:
- Remote:
remotePatterns, Server neu starten width/heightoderfill+ Parent-Höhe- Above-the-fold:
priority, Rest lazy - Responsive:
sizes quality: 90 / 75 / 60 je nach Rolle
<img> durch <Image> ersetzen, Lighthouse laufen lassen – oft +20 Punkte oder mehr.
Bei Problemen den Abschnitt zu häufigen Fehlern durchgehen – die meisten Fälle sind dort abgedeckt. Viele Optionen, aber wenige Kern-Props reichen für den Alltag.
Next.js Image: vollständiger Optimierungsablauf
Von Remote-Config über Performance bis CLS-Vermeidung
⏱️ Estimated time: 2 hr
- 1
Step 1: Remote-Domains konfigurieren
In next.config.js:
• images.remotePatterns-Array
• protocol, hostname, pathname
• Pfadmuster einschränkbar
Beispiel:
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
pathname: '/images/**'
}
]
}
Wichtig: Dev-Server nach Änderung neu starten - 2
Step 2: img durch Image ersetzen
Basis:
• import Image from 'next/image'
• width und height (oder fill)
• alt für SEO
Beispiel:
<Image
src="/hero.jpg"
width={800}
height={600}
alt="Beschreibung"
/> - 3
Step 3: CLS vermeiden
Methode 1: feste Maße
• width und height setzen
• optional aspect-ratio
Methode 2: fill
• Parent: position relative
• Image: fill
• Parent mit fester Höhe
Methode 3: placeholder
• blurDataURL
• placeholder="blur" - 4
Step 4: Lade-Performance optimieren
Above-the-fold:
• priority (bzw. preload in v16)
• quality=90
• im Viewport
Sonstige Bilder:
• Lazy Load (Default)
• quality=75
• sizes für Responsive
Thumbnails:
• quality=60
• kleine width/height - 5
Step 5: Responsive mit sizes
sizes teilt dem Browser mit, welche Breite nötig ist:
<Image
src="/hero.jpg"
width={1200}
height={630}
sizes="(max-width: 768px) 100vw, 50vw"
alt="Beschreibung"
/>
Mobil volle Breite, Desktop halbe Breite – passende Datei wird geladen. - 6
Step 6: Testen und validieren
Performance:
• Lighthouse: LCP und CLS
• Network-Tab: Größe und Format
• WebP/AVIF prüfen
Checkliste:
• alle Remote-Hosts in remotePatterns
• width/height oder fill+Parent
• priority nur für Hero/kritisch
• CLS nahe 0
• Bildvolumen deutlich reduziert
FAQ
Warum der Fehler „Un-configured Host“ bei Remote-Bildern?
Muss die Image-Komponente width und height haben?
Wie vermeide ich Layout-Verschiebung beim Bildladen?
Wann priority verwenden?
Konvertiert Image automatisch Formate?
Wozu dient sizes?
Wie optimiere ich die Bildqualität?
9 Min. Lesezeit · Veröffentlicht am: 19. Dez. 2025 · Aktualisiert am: 14. Juli 2026
Next.js Komplettleitfaden
Wenn du über die Suche hier gelandet bist, kommst du am schnellsten weiter, indem du zum vorherigen oder nächsten Beitrag dieser Serie springst.
Vorheriger
Next.js Caching vollständig verstehen: Wann revalidate richtig einsetzen
Die vier Cache-Ebenen von Next.js im Detail, revalidate, revalidatePath und revalidateTag gezielt nutzen, typische Probleme bei nicht aktualisierten Daten lösen – mit vollständiger Fehlersuche und Best Practices
Teil 25 von 51
Nächster
Next.js Core Web Vitals in der Praxis: LCP, FCP und CLS im Griff
Vollständiger Leitfaden zur Optimierung von LCP, FCP und CLS in Next.js – Lighthouse-Score auf 90+ bringen. Mit 10+ Codebeispielen, typischen Fallstricken und Praxis-Tipps.
Teil 27 von 51
Ähnliche Beiträge
Next.js App Router Einstieg: Kernkonzepte und Grundlagen im Überblick

Next.js App Router Einstieg: Kernkonzepte und Grundlagen im Überblick
Next.js 15 in der Praxis: Wie ich an einem Wochenende ein produktionsreifes Blog-System aufgebaut habe


Kommentare
Melde dich mit GitHub an, um einen Kommentar zu hinterlassen