Ik heb de afgelopen vier jaar afbeeldingen in Next.js-apps geoptimaliseerd, en ik zal je eerlijk zeggen -- het landschap in 2026 ziet er totaal anders uit dan toen next/image voor het eerst verscheen. Google's Core Web Vitals-drempelwaarden zijn strakker geworden, nieuwe afbeeldingsformaten zijn volwassen geworden, en de next/image-component zelf heeft meerdere herschrijvingen ondergaan. Als je afbeeldingen nog steeds op dezelfde manier configureert als in 2023, laat je performance (en rankings) liggen.

Dit is geen samenvatting van de Next.js-documentatie. Dit is wat ik heb geleerd van het uitrollen van tientallen productiesites waar LCP-scores echt belangrijk zijn -- waar een verschil van 200ms in afbeeldingsladen het verschil betekende tussen pagina één en pagina drie.

Inhoudsopgave

Next.js-afbeeldingsoptimalisatie voor Core Web Vitals in 2026

Core Web Vitals in 2026: Wat is er veranderd

Google heeft de Core Web Vitals-drempelwaarden eind 2025 bijgewerkt, en de veranderingen waren niet triviaal. Dit is de huidige stand:

Metriek 2023 "Goed" drempel 2026 "Goed" drempel Wat het meet
LCP ≤ 2,5s ≤ 2,0s Largest Contentful Paint
INP ≤ 200ms ≤ 150ms Interaction to Next Paint
CLS ≤ 0,1 ≤ 0,1 Cumulative Layout Shift
TTFB N.v.t. (geen CWV) Informeel ≤ 600ms Time to First Byte

De LCP-drempel die van 2,5s naar 2,0s daalt, is de verandering die afbeeldingsrijke sites het hardst heeft geraakt. Een halve seconde klinkt niet veel tot je beseft dat voor meer dan 60% van de pagina's het LCP-element een afbeelding is. Meestal een heldenafbeelding, productfoto of aanbevolen artikelminiatuur.

INP die FID vervangt, was al van kracht, maar de verscherpte drempel van 150ms betekent dat zware JavaScript-bundels -- inclusief slecht geconfigureerde lazy-loading-scripts voor afbeeldingen -- je interactiviteitsscores kunnen beschadigen.

CLS is hetzelfde gebleven, wat goed nieuws is. Maar afbeeldingen blijven de nummer één oorzaak van layoutverschuiving wanneer ze geen expliciete afmetingen hebben.

Waarom dit speciaal voor Next.js belangrijk is

Next.js-apps zijn van nature JavaScript-zwaar. Je stuurt React, je stuurt frameworkcode, en als je niet voorzichtig bent, stuur je ook logica voor afbeeldingsoptimalisatie client-side. De combinatie van een strakter LCP-budget en de JS-overhead van een React-app betekent dat je minder ruimte voor fouten hebt dan een statische HTML-site.

Dit is precies waarom we sterk inzetten op Next.js-ontwikkeling -- het framework geeft je ongelooflijke tools, maar alleen als je ze goed configureert.

Hoe next/image echt werkt onder de motorkap

Laten we ontrafelen wat er gebeurt wanneer je <Image /> van next/image gebruikt. Het begrijpen van de pijplijn helpt je betere optimalisatiebeslissingen te nemen.

De aanvraagstroom

  1. Buildtijd: Next.js genereert HTML met een <img>-tag die naar /_next/image?url=...&w=...&q=... verwijst
  2. Eerste aanvraag: De Next.js-afbeeldingsoptimalisatie-API ontvangt de aanvraag, haalt de originele afbeelding op, wijzigt het formaat, converteert het formaat en cacht het resultaat
  3. Volgende aanvragen: De gecachte versie wordt direct bediend

In Next.js 15 (de huidige stabiele versie vanaf begin 2026) gebruikt de afbeeldingsoptimalisatie standaard sharp in Node.js-omgevingen. Op Vercel wordt hun edge-gebaseerde afbeeldingsoptimalisatieservice gebruikt. Op andere platforms valt het terug op sharp of squoosh, afhankelijk van je configuratie.

// Basisgebruik -- maar er gebeurt veel achter deze schermen
import Image from 'next/image';

export default function Hero() {
  return (
    <Image
      src="/hero.jpg"
      alt="Product hero shot"
      width={1200}
      height={630}
      priority
      quality={80}
    />
  );
}

Die priority-prop doet meer dan je denkt. Het voegt fetchpriority="high" toe aan de HTML, schakelt lazy loading uit en genereert een preload <link>-tag in de <head>. We gaan hier later op teruggaan waarom dit belangrijk is voor LCP.

De configuratie die de meeste mensen nooit aanraken

Je next.config.js (of next.config.ts als je bent gemigreerd) heeft een images-sleutel die alles regelt:

// next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    minimumCacheTTL: 31536000, // 1 jaar in seconden
    dangerouslyAllowSVG: false,
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'your-cms.com',
        pathname: '/assets/**',
      },
    ],
  },
};

De volgorde van de formats-array is belangrijk. Next.js probeert eerst AVIF, dan valt terug op WebP. AVIF-codering is langzamer maar produceert kleinere bestanden -- deze afweging is belangrijk om te begrijpen.

Het LCP-probleem: Waarom je heldenafbeelding je score vermoord

Hier is het scenario dat ik bij bijna elke audit zie: een prachtige heldenafbeelding, boven de vouw, die 3+ seconden duurt om te renderen. De ontwikkelaar gebruikte next/image, dacht dat ze klaar waren, en ging verder. Maar de score is verschrikkelijk.

De gebruikelijke verdachten:

1. De `priority`-prop vergeten

Standaard lazy-loaded next/image alles. Dat is prima voor afbeeldingen onder de vouw, maar catastrofaal voor je LCP-element. Zonder priority, ontdekt de browser de afbeelding laat, nadat JavaScript is gehydrateerd en de intersection observer in werking is gesteld.

// ❌ Dit lazy-loaded je LCP-afbeelding
<Image src="/hero.jpg" alt="Hero" width={1200} height={630} />

// ✅ Dit preloadt het
<Image src="/hero.jpg" alt="Hero" width={1200} height={630} priority />

2. Te sterk comprimeren met lage kwaliteitswaarden

Ik heb teams zien instellen quality={50} denken dat kleiner = sneller. Maar als de afbeelding wazig ziet, moet Chromes LCP-algoritme nog steeds wachten tot het volledig is gerenderd. En op high-DPI-schermen triggeren kwaliteitswaarden onder de 70 vaak zichtbare artefacten die het design goedkoop doen lijken.

Mijn vuistregel: kwaliteit 75-85 voor foto's, kwaliteit 90+ voor afbeeldingen met tekst of scherpe randen.

3. `sizes` niet correct gebruiken

Het sizes-attribuut vertelt de browser welke afbeeldingsbreedte moet worden aangevraagd voordat CSS is geparseerd. Zonder het valt Next.js terug op 100vw, wat betekent dat mobiele apparaten afbeeldingen in desktopgrootte downloaden.

<Image
  src="/hero.jpg"
  alt="Hero"
  fill
  priority
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
/>

Deze ene propwijziging heeft mij de grootste LCP-verbeteringen gegeven -- soms 400-800ms op mobiel.

Next.js-afbeeldingsoptimalisatie voor Core Web Vitals in 2026 - architectuur

Format-oorlogen: AVIF vs WebP vs JPEG XL in 2026

Het format-landschap is aanzienlijk afgevlakt. Hier staat het:

Format Browserondersteuning (2026) Compressie Coderingssnelheid Ideaal voor
AVIF ~95% wereldwijd Uitstekend (30-50% kleiner dan WebP) Traag Foto's, heldenafbeeldingen
WebP ~98% wereldwijd Goed (25-35% kleiner dan JPEG) Snel Algemeen gebruik
JPEG XL ~45% (Chrome heeft het verwijderd) Uitstekend Gemiddeld Niet aanbevolen voor web
JPEG Universeel Basislijn Snel Alleen terugval
PNG Universeel Slecht voor foto's Snel Transparantie, schermafbeeldingen

JPEG XL had een veelbelovende specificatie, maar Chromes besluit om ondersteuning eind 2023 in te trekken heeft het voor webgebruik effectief onschadelijk gemaakt. Safari heeft ondersteuning toegevoegd, Firefox heeft gedeeltelijke ondersteuning, maar je kunt er niet op rekenen.

Mijn aanbeveling: Stel formats: ['image/avif', 'image/webp'] in en vergeet het. Next.js handelt content negotiation automatisch af via de Accept-header.

De AVIF-coderingskosten

Hier is iets dat de docs niet genoeg benadrukken: AVIF-codering is CPU-intensief. Bij een eerste aanvraag naar je Next.js-server kan het coderen van een AVIF-afbeelding van 1200px 2-5 seconden duren op een bescheiden server. Die eerste bezoeker betaalt de kosten.

Strategieën om dit te beperken:

  • Pre-genereer bij buildtijd met behulp van next export of aangepaste buildscripts
  • Gebruik een CDN met ingebouwde afbeeldingsoptimalisatie (Cloudflare Images, Imgix, Cloudinary)
  • Warm je cache na implementatie met een script dat alle kritieke afbeeldings-URL's aanroept
# Eenvoudig cache-warmingsscript
#!/bin/bash
URLs=("https://yoursite.com/_next/image?url=%2Fhero.jpg&w=1200&q=80"
      "https://yoursite.com/_next/image?url=%2Fhero.jpg&w=750&q=80")

for url in "${URLs[@]}"; do
  curl -s -o /dev/null -H "Accept: image/avif,image/webp" "$url"
  echo "Warmed: $url"
done

Responsieve afbeeldingen goed gedaan

Responsieve afbeeldingen in Next.js zijn niet moeilijk, maar ze vereisen wel begrip van hoe deviceSizes, imageSizes en de sizes-prop samenwerken.

Het `fill` layout-patroon

Voor afbeeldingen waarvan je de aspectratio niet kent op buildtijd (CMS-inhoud, gebruikersupload's), gebruik je de fill-prop:

<div className="relative aspect-[16/9] w-full">
  <Image
    src={post.featuredImage}
    alt={post.title}
    fill
    className="object-cover"
    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  />
</div>

De ouder div met relative-positionering en een aspectratio is kritiek. Zonder het worden fill-afbeeldingen samengevouwen tot nulhoogte en je krijgt een CLS-score die je doen gruwelen.

Art direction met ``

Soms heb je verschillende uitsnijdingen voor verschillende schermgroottes. next/image ondersteunt <picture> niet native, maar je kunt hier omheen werken:

// Art direction workaround
export function ResponsiveHero({ mobileSrc, desktopSrc, alt }) {
  return (
    <>
      <div className="block md:hidden relative aspect-[9/16] w-full">
        <Image src={mobileSrc} alt={alt} fill priority sizes="100vw" />
      </div>
      <div className="hidden md:block relative aspect-[16/9] w-full">
        <Image src={desktopSrc} alt={alt} fill priority sizes="100vw" />
      </div>
    </>
  );
}

Ja, dit downloadt de HTML van beide afbeeldingen, maar alleen één wordt gerenderd, en de verborgen wordt niet geladen dankzij standaard lazy loading defaults (je zou priority alleen toepassen op die welke overeenkomt met de viewport).

CDN- en edge-optimalisatiestrategieën

Als je Next.js zelf host (en veel teams doen dat), heb je een CDN-strategie voor afbeeldingen nodig.

Optie 1: Laat Vercel het afhandelen

Vercel's afbeeldingsoptimalisatie draait aan de edge. Voor de meeste projecten is dit het gemakkelijkste pad. Vanaf 2026 omvat het Pro-plan van Vercel 5.000 bronafbeeldingen met optimalisatie, met extra afbeeldingen voor $5 per 1.000. Enterprise-plannen hebben aangepaste prijzen.

Optie 2: Externe afbeeldingsoptimalisatieservice

Cloudinary, Imgix en Cloudflare Images werken allemaal met Next.js via de loader-prop of een aangepaste loader:

// next.config.js met Cloudinary
module.exports = {
  images: {
    loader: 'custom',
    loaderFile: './lib/cloudinary-loader.js',
  },
};
// lib/cloudinary-loader.js
export default function cloudinaryLoader({ src, width, quality }) {
  const params = [
    `w_${width}`,
    `q_${quality || 'auto'}`,
    'f_auto',
    'c_limit',
  ];
  return `https://res.cloudinary.com/your-cloud/image/upload/${params.join(',')}${src}`;
}
Service Gratis laag Pro-prijzen (2026) Edge-knooppunten AVIF-ondersteuning
Cloudinary 25 credits/maand $89/maand (25GB) 60+ Ja
Imgix Geen $100/maand (100GB) Wereldwijd Ja
Cloudflare Images Geen $5/maand (100K varianten) 310+ Ja
Vercel (ingebouwd) 1.000 afbeeldingen (Hobby) Inbegrepen in Pro Edge Ja

Voor onze headless CMS-ontwikkelingsprojecten gebruiken we meestal Cloudinary of de ingebouwde afbeeldingspijplijn van het CMS (Sanity, Contentful en Hygraph hebben allemaal redelijke afbeeldings-API's).

Optie 3: Cloudflare Polish + Next.js

Als je al achter Cloudflare zit, kan hun Polish-functie formaatconversie aan de edge afhandelen. Je zou Next.js-afbeeldingsoptimalisatie uitschakelen en Cloudflare het werk laten doen:

module.exports = {
  images: {
    unoptimized: true, // Laat Cloudflare het afhandelen
  },
};

Ik ben geen groot fan van deze benadering omdat je de responsieve sizing verliest die next/image biedt, maar het werkt voor eenvoudigere setups.

Het meten wat ertoe doet: Tools en benchmarks

Je kunt niet verbeteren wat je niet meet. Hier is mijn teststack:

Lab-tools

  • Chrome DevTools Lighthouse (v12 vanaf 2026): Nog steeds het startpunt. Draai het in incognito zonder extensies.
  • WebPageTest: Stel het in op Dulles, VA op een Moto G Power met 4G. Dit vertegenwoordigt een realistische "langzame" gebruiker.
  • Unlighthouse: Scant bulk je hele site. Geweldig om pagina's die je bent vergeten te vinden.

Veldgegevens

  • Chrome UX Report (CrUX): De werkelijke gegevens die Google voor rankingssignalen gebruikt. Beschikbaar in PageSpeed Insights en BigQuery.
  • web-vitals.js: Voeg het toe aan je app om echte gebruikersmetrieken in te verzamelen:
// app/layout.tsx
import { onLCP, onINP, onCLS } from 'web-vitals';

if (typeof window !== 'undefined') {
  onLCP(console.log);
  onINP(console.log);
  onCLS(console.log);
}

In productie stuur je deze naar je analyticsplatform in plaats van console.log. We gebruiken een combinatie van Vercel Speed Insights en een aangepast eindpunt dat naar BigQuery schrijft.

Benchmarktargets voor 2026

Gebaseerd op de sites die we dit jaar hebben geaudit, ziet "goed" eruit voor image-rijke Next.js-sites:

  • LCP op mobiel (p75): < 1,8s (geeft je buffer onder de 2,0s-drempel)
  • Totaal afbeeldingsgewicht boven de vouw: < 200KB
  • Laadtijd van heldenafbeelding: < 800ms op 4G
  • CLS van afbeeldingen: 0

Geavanceerde technieken die echt resultaat opleveren

Blur-aanduidingen met BlurHash

Next.js ondersteunt placeholder="blur" native voor statische imports. Voor dynamische afbeeldingen (van een CMS) moet je blur-gegevens-URL's genereren:

import { getPlaiceholder } from 'plaiceholder';

export async function getStaticProps() {
  const { base64 } = await getPlaiceholder('/path/to/image.jpg');
  return {
    props: { blurDataURL: base64 },
  };
}

// In component
<Image
  src={dynamicUrl}
  alt="Dynamic image"
  fill
  placeholder="blur"
  blurDataURL={blurDataURL}
/>

Dit verbetert LCP niet direct, maar het verbetert waargenomen performance drastisch en voorkomt CLS.

HTTP/3 en Early Hints

Als je CDN HTTP/3 ondersteunt (Cloudflare, Fastly en Vercel doen allemaal), kunt je 103 Early Hints gebruiken om de LCP-afbeelding al te starten voordat het HTML-document volledig is gegenereerd:

// middleware.ts
import { NextResponse } from 'next/server';

export function middleware(request) {
  const response = NextResponse.next();
  
  if (request.nextUrl.pathname === '/') {
    response.headers.set(
      'Link',
      '</hero.avif>; rel=preload; as=image; type="image/avif"'
    );
  }
  
  return response;
}

Skelet-laden met CSS `content-visibility`

Voor lange pagina's met veel afbeeldingen vertelt content-visibility: auto de browser om off-screen-inhoud helemaal niet te renderen:

.image-grid-item {
  content-visibility: auto;
  contain-intrinsic-size: 300px 200px; /* Geschatte grootte */
}

Dit verlaagde INP met 30-40ms op een productaanbiedingspagina die we vorig kwartaal hebben geoptimaliseerd.

Veelvoorkomende fouten die ik bij elke audit zie

  1. next/image gebruiken voor decoratieve SVG's: Gebruik gewoon een <img>-tag of voeg de SVG inline in. De optimalisatiepijplijn voegt overhead toe zonder voordeel.

  2. unoptimized wereldwijd instellen omdat "afbeeldingen wazig zien": Fix de kwaliteitsinstelling in plaats daarvan. unoptimized bypast alles.

  3. Alt-tekst vergeten: Dit is niet alleen toegankelijkheid -- Google's afbeeldingszoekopdracht brengt verkeer, en het heeft alt-tekst nodig om je afbeeldingen te indexeren.

  4. minimumCacheTTL niet instellen: De standaard is 60 seconden. Dat betekent dat je server dezelfde afbeelding elke minuut onder belasting opnieuw optimaliseert. Stel het minimaal in op 2592000 (30 dagen).

  5. Massieve bronafbeeldingen gebruiken: Een DSLR-foto van 6000x4000px uploaden en verwachten dat Next.js dit afhandelt. Pre-verwerk je bronafbeeldingen tot maximaal 2x je grootste displaygrootte.

  6. Het Network-tabblad negeren: Open DevTools, filter op Img, sorteer op grootte. Je vindt problemen in 30 seconden.

Als je met deze problemen kampt op een productiesite, dat is precies het soort probleem dat we oplossen. Bekijk onze prijzen of neem rechtstreeks contact op -- we doen performance-audits als zelfstandige opdrachten.

Veelgestelde vragen

Converteert next/image afbeeldingen automatisch naar AVIF? Ja, als je 'image/avif' in je images.formats-array in next.config.js hebt (dit is standaard opgenomen sinds Next.js 14). De conversie gebeurt op aanvraag wanneer een browser een Accept-header stuurt die image/avif bevat. Het eerste verzoek is langzamer vanwege codering, maar volgende verzoeken worden uit cache bediend.

Hoeveel vermindert AVIF de bestandsgrootte van afbeeldingen in vergelijking met WebP? In onze tests op honderden productieafbeeldingen is AVIF gemiddeld 30-50% kleiner dan WebP bij gelijkwaardige visuele kwaliteit, en 50-70% kleiner dan JPEG. De winsten zijn het dramatischst op fotografische inhoud. Voor schermafbeeldingen of afbeeldingen met tekst wordt het verschil smaller tot 15-25%.

Moet ik priority op meerdere afbeeldingen gebruiken? Gebruik het spaarzaam -- alleen op afbeeldingen die echt boven de vouw zijn en zichtbaar zijn bij het eerste laden. Het toevoegen van priority aan meer dan 2-3 afbeeldingen verslaat het doel omdat de browser niet alles gelijktijdig kan prioriteren. Voor je homepagina-hero en misschien een logo, dat is het.

Waarom is mijn LCP nog steeds traag, zelfs met next/image en priority? De meest voorkomende reden is dat je serverresponsetijd (TTFB) je budget opeet. Als je Next.js-server 800ms nodig heeft om te reageren, heb je slechts 1,2 seconden over voor de afbeelding om te laden en te renderen. Andere schuldigen: rendering-blokkerende CSS, grote JavaScript-bundels die hydratatie vertragen, of de afbeeldingsbron bevindt zich op een trage originserver.

Kan ik next/image gebruiken met statische exports (next export)? Niet met de ingebouwde optimalisatie. Statische exports vereisen images.unoptimized: true of een aangepaste loader die naar een externe service wijst, zoals Cloudinary of Imgix. Dit is één reden waarom we soms Astro aanbevelen voor puur statische sites -- de afbeeldingsafhandeling ervan vereist geen draaiende server.

Hoe verwerk ik afbeeldingen van een headless CMS met next/image? Voeg het afbeeldingsdomein van het CMS toe aan images.remotePatterns in je configuratie. De meeste headless CMS-platforms (Sanity, Contentful, Storyblok, Hygraph) hebben hun eigen API's voor afbeeldingstransformatie. Je kunt de afbeeldingen laden via de native pijplijn van het CMS of Next.js deze laten optimaliseren. We geven over het algemeen de voorkeur aan de native pijplijn van het CMS voor headless CMS-projecten omdat dit de serverbelasting vermindert.

Wat is de impact van afbeeldingsoptimalisatie op Core Web Vitals-rankingssignalen? Google bevestigde in 2025 dat Core Web Vitals een rankingssignaal blijven, hoewel inhoudsrelevantie nog steeds domineert. Dit gezegd zijnde, kan CWV voor competitieve zoekopdrachten waar inhoudsgebruikelijkheid vergelijkbaar is in toptresultaten de doorslag geven. We hebben gezien dat sites 3-8 posities opschuiven na LCP-problemen op te lossen die primair werden veroorzaakt door niet-geoptimaliseerde afbeeldingen.

Moet ik alle afbeeldingen onder de vouw lazy-loaden? Ja, en Next.js doet dit standaard (tenzij je priority toevoegt). Het native loading="lazy"-attribuut is wat next/image onder de motorkap gebruikt. Er is geen noodzaak meer voor een JavaScript-gebaseerde lazy loading-bibliotheek -- browser-native lazy loading is sinds 2022 stabiel in alle grote browsers.