Gambar biasanya 40-80% dari total berat byte halaman web. Sebelum saya mengoptimalkan gambar matthewswong.com, bagian hero menyajikan JPEG 1,4MB di ponsel. Setelah mengkonversi ke AVIF dengan optimizer bawaan Next.js, turun menjadi 180KB — pengurangan 87% tanpa kehilangan kualitas yang terlihat. Perubahan tunggal itu memindahkan LCP saya dari 3,1d menjadi 1,8d di ponsel.
WebP memberikan penghematan ukuran file 25-40% dibandingkan JPEG dengan kualitas setara, dengan dukungan browser hampir universal (96%+ pada 2025). AVIF lebih jauh — penghematan 45-65% dibandingkan JPEG — tetapi dengan dukungan browser yang sedikit lebih rendah (90%+ pada 2025). Next.js menangani keputusan format secara otomatis: memeriksa header Accept dari browser, menyajikan AVIF jika didukung, fallback ke WebP, lalu fallback ke format asli.
Komponen next/image mencegat permintaan gambar dan menjalankannya melalui pipeline optimisasi gambar Next.js. Pada permintaan pertama, Next.js mengubah ukuran gambar, mengkonversinya ke format optimal untuk browser yang meminta, dan menyimpan hasilnya di disk. Permintaan berikutnya untuk gambar yang sama dengan ukuran yang sama mengenai cache dan kembali seketika.
Perubahan yang paling berdampak untuk LCP adalah menambahkan prop `priority` ke gambar hero Anda. Tanpanya, Next.js menambahkan Intersection Observer untuk lazy-load gambar — artinya tidak mulai mengunduh sampai gambar masuk viewport. Untuk gambar hero yang terlihat pada pemuatan pertama, ini sangat buruk untuk LCP. Prop `priority` mengeluarkan `fetchpriority='high'` pada tag img dan menghapus perilaku lazy-loading. Jangan pernah lazy-load gambar LCP Anda.
Format Comparison (same image, equivalent quality):
─────────────────────────────────────────────────────
JPEG (original) 1,400 KB Baseline
WebP 860 KB -39% vs JPEG
AVIF 180 KB -87% vs JPEG ✓ Best
Browser Support (2025):
AVIF: Chrome 85+, Firefox 93+, Safari 16+ → ~90% global
WebP: Chrome 32+, Firefox 65+, Safari 14+ → ~96% global
Next.js format selection (Accept header):
Browser sends: Accept: image/avif,image/webp,*/*
Next.js serves: AVIF → WebP → original
(most compressed format the browser accepts)
next.config.ts:
images: {
formats: ['image/avif', 'image/webp'], // AVIF preferred
deviceSizes: [640, 750, 828, 1080, 1200, 1920],
minimumCacheTTL: 2592000, // 30 days
}Dari pengalaman saya mengoptimalkan matthewswong.com: gunakan `placeholder='blur'` dengan `blurDataURL` pada semua gambar hero dan di atas fold. Anda dapat menghasilkan blurDataURL secara otomatis dengan paket `plaiceholder` pada waktu build. Ini mengisi ruang dengan pratinjau beresolusi rendah yang blur sementara gambar penuh dimuat, menghilangkan CLS dari pemuatan gambar dan meningkatkan performa yang dirasakan secara signifikan.
Setelah iterasi melalui beberapa proyek, saya telah mendarat pada next.config.ts produksi yang mencakup tombol optimisasi gambar utama. Pengaturan kunci adalah: format (AVIF pertama, lalu WebP), deviceSizes (mencocokkan breakpoint umum), imageSizes (untuk thumbnail yang lebih kecil), dan minimumCacheTTL (diatur ke 30 hari untuk aset statis).
Jika Anda memuat gambar dari URL eksternal, Anda perlu mengkonfigurasi remotePatterns di next.config.ts. Ini adalah fitur keamanan — tanpanya, seseorang dapat membuat permintaan yang membuat server Anda mengunduh dan mengoptimalkan URL sembarang. Konfigurasikan hostname dan pola path opsional untuk setiap sumber tepercaya.
// next.config.ts — production image optimization config
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
images: {
formats: ["image/avif", "image/webp"],
deviceSizes: [640, 750, 828, 1080, 1200, 1920],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 60 * 60 * 24 * 30, // 30 days
remotePatterns: [
{
protocol: "https",
hostname: "assets.contentful.com", // your CMS
},
],
},
}
export default nextConfig
// Hero component — LCP-critical image
import Image from "next/image"
import { getPlaiceholder } from "plaiceholder" // npm i plaiceholder
// At build time, generate blur placeholder:
const { base64 } = await getPlaiceholder(heroImageBuffer)
export function HeroSection() {
return (
<Image
src="/hero.jpg"
alt="Portfolio hero — Matthews Wong"
width={1200}
height={630}
priority // fetchpriority="high" — never lazy-load LCP
placeholder="blur"
blurDataURL={base64} // low-res preview while loading
sizes="100vw" // hero spans full viewport width
/>
)
}
// Below-fold blog card image — lazy-load correctly
export function BlogCard({ image, title }: { image: string; title: string }) {
return (
<Image
src={image}
alt={title}
width={600}
height={315}
// No priority — lazy-load is correct for below-fold images
sizes="(min-width: 768px) 600px, 100vw"
/>
)
}Prop `sizes` pada next/image memberi tahu browser seberapa lebar gambar akan berada pada lebar viewport yang berbeda. Tanpa prop `sizes` yang akurat, browser default ke 100vw — artinya mengunduh gambar selebar viewport penuh bahkan untuk thumbnail 300px. Mendapatkan ini dengan benar dapat mengurangi payload gambar 30-50% untuk gambar di bawah fold.
Komponen Image Next.js tidak mengoptimalkan file SVG atau GIF — menyajikannya apa adanya. Untuk GIF animasi, ini adalah masalah: GIF animasi terkenal besar. Jika Anda menyajikan konten animasi, konversikan ke format video WebM atau AVIF dan gunakan elemen video. GIF 5MB dapat menjadi WebM 300KB.
Pendekatan default Next.js adalah optimisasi runtime — gambar diproses pada permintaan pertama. Ini baik untuk sebagian besar kasus, tetapi untuk ekspor statis (`output: 'export'`) Next.js tidak dapat melakukan optimisasi runtime karena tidak ada server. Dalam kasus itu, Anda perlu pra-optimalkan gambar selama build menggunakan alat seperti sharp, imagemin, atau Squoosh.
Setelah mengaktifkan AVIF dan menambahkan priority ke gambar hero pada matthewswong.com, LCP lab meningkat dari 2,8d menjadi 1,4d. LCP lapangan meningkat dari 3,1d menjadi 1,9d selama 28 hari berikutnya. Total payload gambar di halaman beranda turun dari 1,8MB menjadi 340KB. Pelajarannya: optimisasi gambar adalah pekerjaan performa ROI tertinggi yang dapat Anda lakukan di sebagian besar situs berbasis konten.