Aplikasi React yang lambat dapat mematikan pengalaman pengguna. Seringkali, aset gambar di aplikasilah yang menyebabkan pelambatan. Mengoptimalkan gambar dapat memberikan peningkatan besar pada kinerja aplikasi apa pun. Dalam postingan ini, kita akan membahas strategi pengoptimalan gambar secara lengkap dan menurunkan LCP dari ~8 detik menjadi ~1 detik.
Jika Anda ingin menonton blog ini dalam format video, Anda bisa mengikuti cara di atas.
Titik awal kode untuk aplikasi ini ditemukan di GitHub di sini.
Langkah 0: Temukan gambar hambatan
Sebelum mengubah apa pun, kita perlu mengetahui apa yang sedang kita kerjakan. Mari kita temukan gambar yang paling menyebabkan pelambatan. Berikut cara menemukannya:
- Buka Chrome DevTools,
- navigasikan ke tab Jaringan,
- dan throttle ke Slow 4G dengan cache dinonaktifkan.
Pembatasan ini penting karena menyimulasikan kondisi pengguna sebenarnya. Sebagian besar pengguna tidak menggunakan internet tercepat.
Untuk menemukan gambar paling lambat, cari:
- Gambar LCP: elemen terbesar yang terlihat pada pemuatan awal, biasanya gambar pahlawan
- Ukuran berkas: berapa banyak data yang ditransfer
- Waktu muat: berapa lama waktu yang dibutuhkan gambar untuk dirender sepenuhnya
Dalam aplikasi contoh kami, gambar latar belakang pahlawan adalah JPEG yang dibundel secara lokal dengan ukuran 380 KB. Itulah titik awal kami:
Kami memulai dengan LCP 8,18 detik.
Langkah 1: Kompresi gambar
Perbaikan pertama dan tercepat adalah mengompresi ukuran gambar. Itu tidak memerlukan perubahan infrastruktur, tidak ada konfigurasi, dan tidak ada kode. Dengan menggunakan alat yang tepat, Anda dapat memotong ukuran gambar menjadi dua tanpa kehilangan kualitas yang nyata.
Beberapa alat untuk kompresi gambar:
- Squoosh: Alat berbasis browser dengan pratinjau langsung berdampingan dan pengaturan kompresi yang dapat disesuaikan. Terbaik untuk gambar satu kali atau saat Anda menginginkan kontrol yang lebih halus.
- ImageOptim: Aplikasi desktop yang menghapus metadata dan mengompresi gambar dengan kehilangan kualitas minimal.
- TinyPNG: Alat web drag-and-drop sederhana yang berfungsi baik untuk PNG dan JPEG.
- Alat CLI: ideal untuk kompresi batch sebagai bagian dari proses pembangunan Anda.
imageoptim-cliimageminImageMagick
Hasil
Mengompresi gambar pahlawan dari 380 KB menjadi 180 KB menghasilkan paket yang jauh lebih kecil tanpa perbedaan kualitas visual yang nyata:

Langkah 2: Pindahkan gambar ke CDN
Menyajikan gambar langsung dari app bundle Anda adalah salah satu kesalahan kinerja paling umum di aplikasi React. Ketika sebuah gambar dibundel secara lokal, setiap pengguna mengunduhnya dari server asal yang sama, di mana pun mereka berada, oleh karena itu memiliki gambar sebagai bagian dari bundel lokal adalah sebuah antipattern.
Jaringan Pengiriman Konten (CDN) memecahkan masalah ini dengan:
Mengunggah gambar ke CDN
CDN populer untuk pengiriman gambar adalah Cloudinary. Ia menawarkan tingkat gratis yang melimpah dan API transformasi gambar berbasis URL yang kuat dengan cepat. Ini sempurna untuk kasus penggunaan kami. Untuk mengunggah gambar di Cloudinary:
- Buat akun Cloudinary gratis
- Unggah gambar Anda melalui dasbor Cloudinary atau CLI
- Salin URL CDN yang dihasilkan
- Ganti referensi gambar lokal Anda di komponen React Anda:
Hasil
Setelah pindah ke Cloudinary, LCP berkurang dari 8,8 detik → 5,39 detik.
Langkah 3: Menggunakan format gambar modern
Format gambar seperti JPEG dan PNG tidak dirancang untuk web modern. Format baru seperti WebP dan AVIF menawarkan kompresi yang jauh lebih baik dengan kualitas visual yang sama:

Berikut adalah tabel yang membahas tentang berbagai format gambar yang tersedia saat ini dan mana yang lebih disukai untuk kasus penggunaan tertentu:
| Jenis | Format berkas | Tipe MIME | Penggunaan |
|---|---|---|---|
| AVIF | Format File Gambar AV1 (.avif) | gambar/avif | 1. Menawarkan kompresi yang jauh lebih baik daripada PNG atau JPEG.
2. Pilihan bagus untuk gambar dan gambar animasi. 3. Periksa dukungan browser sebelum menggunakan. |
| WEBP | Format Gambar Web (.webp) | gambar/webp | 1. Sedikit kurang bagus dibandingkan dengan AVIF tetapi masih menawarkan kompresi yang lebih baik dibandingkan PNG atau JPEG.
2. Pilihan luar biasa untuk gambar dan gambar animasi. 3. Didukung dengan baik di semua browser. |
| jpeg | Gambar Kelompok Pakar Fotografi Bersama (.jpeg, .jpg) | gambar/jpeg | 1. Kompresi yang hilang.
2. Berfungsi dengan baik untuk gambar diam. |
| PNG | Grafik Jaringan Portabel (.png) | gambar/png | 1. Kompresi gambar sumber yang lebih tepat. Bekerja lebih baik daripada JPEG.
2. Pilihan yang disukai saat menggunakan gambar transparan. |
| SVG | Grafik Vektor yang Dapat Diskalakan (.svg) | gambar/svg+xml | 1. Format gambar vektor.
2. Lebih disukai untuk elemen seperti ikon, diagram, dll., yang harus diskalakan secara akurat pada ukuran berbeda. |
Sumber:
Pendeknya, avif Dan webp format gambar menawarkan kompresi yang lebih unggul dibandingkan dengan jpeg Dan png. Meskipun AVIF menawarkan kompresi yang lebih baik dibandingkan dengan WebP, AVIF didukung di versi terbaru semua browser utama. WebP memiliki dukungan browser yang lebih luas saat ini.
Mengonversi ke format modern
1. Beralih dengan cepat menggunakan CDN seperti Cloudinary
Salah satu fitur Cloudinary yang paling berguna adalah konversi format sambil jalan melalui parameter URL. Anda dapat mengganti format tanpa mengunggah ulang gambar:
// Original JPEG // Convert to WebP — just change the extension // Convert to AVIF
Lebih baik lagi, gunakan f_auto agar Cloudinary secara otomatis menyajikan format terbaik yang didukung browser:
// f_auto picks WebP, AVIF, or JPEG depending on the browser
Anda dapat merangkainya dengan q_auto untuk pengoptimalan kualitas otomatis juga:
// Best format + optimal quality — the most common production setup
Ini berarti pengguna Chrome mendapatkan AVIF, pengguna Safari mendapatkan WebP, dan browser lama mendapatkan JPEG asli, semuanya dari satu URL, tanpa kode tambahan.
2. Menggunakan alat baris perintah
Untuk apa pun selain beberapa gambar, build pipeline, CI, alur kerja bernaskah, dan alat CLI adalah pendekatan yang tepat. Yang paling berguna adalah cwebp / avifenc — pembuat enkode referensi untuk WebP dan AVIF. Diinstal melalui Homebrew, mereka memberi Anda kontrol codec langsung:
# Convert to WebP at quality 80 cwebp -q 80 hero.png -o hero.webp # Convert to AVIF avifenc --min 20 --max 40 hero.png hero.avif
sharp-cli: Berbasis node, dibangun di atas libvips. Cepat, dipelihara secara aktif, bagus untuk pemrosesan batch:
npm i -g sharp-cli # Convert a folder of images to WebP sharp -i ./images/*.jpg -o ./dist/ --webp-quality 80
Hasil
Beralih dari JPEG ke WebP menurunkan LCP kami dari 5,39 detik → 2,87 detik:
Langkah 4: Mengoptimalkan kualitas dan ukuran area pandang pengguna
Pengguna melihat aplikasi di perangkat yang berbeda. Penting untuk memberikan ukuran dan kualitas gambar yang sesuai berdasarkan perangkat pengguna. Misalnya, pengguna yang melihat media pada layar retina akan memerlukan gambar dengan kualitas lebih tinggi dibandingkan pengguna yang melihat media yang sama pada layar resolusi standar. Hal ini karena layar retina memiliki kerapatan piksel lebih tinggi (biasanya 2x standar), yang berarti layar tersebut memerlukan gambar dengan resolusi dua kali lipat agar tampak tajam dan jernih. Menayangkan gambar beresolusi rendah yang sama ke semua perangkat menghasilkan visual buram atau berpiksel pada layar DPI tinggi:
- Gambar responsif: HTML
<picture>elemen memungkinkan pengembang untuk menyajikan gambar yang dioptimalkan secara kondisional berdasarkan resolusi layar perangkat dan ukuran area pandang, semuanya secara asli di browser tanpa memerlukan JavaScript. - Pengaturan kualitas: Dengan alat seperti Cloudinary, kita dapat memilih tingkat kualitas optimal untuk setiap gambar. Ini berguna ketika Anda menampilkan gambar yang perlu ditampilkan dalam format yang lebih kecil, seperti thumbnail, atau pratinjau buram. Itu
q_autoparameter menganalisis konten gambar dan memilih pengaturan kualitas yang menyeimbangkan ukuran file dan fidelitas visual. Ini memiliki empat sub-varian –q_auto:best,q_auto:good(default),q_auto:ecoDanq_auto:lowmasing-masing menargetkan poin berbeda dalam hal kualitas/ukuran file.
Menggabungkan kedua teknik ini, kita dapat menggunakan <picture> elemen bersama dengan q_auto untuk memberikan kualitas gambar optimal yang sesuai dengan area pandang pengguna:
<picture>
{/* Small screens — phones under 640px */}
<source
media="(max-width: 640px)"
srcSet="
/>
{/* Medium screens — tablets up to 1024px */}
<source
media="(max-width: 1024px)"
srcSet="
/>
{/* Large screens — desktops and above */}
<source
media="(min-width: 1920px)"
srcSet="
/>
{/* Fallback img — always required */}
<img
src="
alt="Hero background"
/>
</picture>
Browser mengevaluasi masing-masing <source> elemen secara berurutan dan menggunakan elemen pertama yang media kondisi cocok. Jika tidak ada yang cocok, atau jika browser tidak mendukung <picture>itu jatuh kembali ke <img> tag — itulah sebabnya fallback <img> selalu diperlukan.
Hasil
Gambar responsif memastikan pengguna seluler mengunduh sebagian kecil data dibandingkan dengan desktop. Dikombinasikan dengan langkah sebelumnya, LCP kami meningkat menjadi 2,33 detik:
Langkah 5: Tetapkan prioritas pemuatan
Tidak semua gambar dibuat sama. Beberapa gambar perlu segera ditampilkan kepada pengguna, seperti gambar pahlawan, dan beberapa gambar mungkin lambat dimuat hingga pengguna benar-benar menggulir ke bawah ke halaman. Oleh karena itu, prioritas gambar perlu diatur dengan tepat.
Prioritaskan gambar LCP
Kami akan mengaturnya fetchPriority dari gambar LCP kami: spanduk pahlawan. Untuk mengatur fetchPriority dengan a <picture> elemen, kita dapat menggunakan proses dua langkah:
1. Atur fetchPriority dari default img –
<img src=" alt="Hero background" fetchpriority="high" />
2. Pramuat aset gambar untuk ukuran area pandang yang paling umum sehingga browser mulai mengambil gambar bahkan sebelum ia menguraikan pohon komponen Anda:
<head>
<link
rel="preload"
as="image"
href="
/>
</head>
Malas memuat yang lainnya
Untuk gambar di paro bawah, tunda pemuatan hingga pengguna menggulir di dekatnya:
<img src=" alt="Video thumbnail" loading="lazy" />
Hasil
Pengaturan fetchpriority="high" dan memuat gambar pahlawan sebelumnya memberi kami peningkatan kecil namun berarti, menghadirkan LCP 2.30 detik pada pemuatan pertama:
Langkah 6: Aktifkan cache
Segala sesuatu yang telah kami lakukan sejauh ini mempercepat Pertama mengunjungi. Caching mempercepat setiap kunjungan setelah itu.
Saat CDN menyajikan gambar, CDN dapat melampirkan header cache yang memberi tahu browser untuk menyimpan gambar secara lokal. Pada kunjungan berulang, browser menyajikan gambar dari cache lokalnya alih-alih membuat permintaan jaringan sama sekali.
Cloudinary otomatis disetel Cache-Control header pada tanggapannya. Untuk caching maksimum, konfigurasikan file long max-age:
Cache-Control: public, max-age=31536000, immutable
A max-age dari 31536000 menyimpan gambar dalam cache selama satu tahun. Hal ini aman untuk dilakukan karena URL Cloudinary menyertakan pengidentifikasi versi, jadi jika Anda memperbarui gambar, URL akan berubah, dan pengguna selalu mendapatkan versi terbaru.
Anda juga dapat mengonfigurasi header cache di server Anda sendiri atau konfigurasi edge jika Anda menghosting sendiri:
// Express.js example
app.use('/images', express.static('public/images', {
maxAge: '1y',
immutable: true,
}));
Hasil
Dengan mengaktifkan caching, pengunjung berulang memuat gambar pahlawan secara instan dari cache lokal mereka, menjatuhkan LCP ke dalamnya 1,22 detik!:
Ringkasan
Berikut kinerja setiap langkah pengoptimalan:
| Melangkah | Tindakan | LCP |
|---|---|---|
| Dasar | JPEG lokal 380 KB | 8,8 detik |
| Langkah 1 | Kompresi gambar | ~7 detik |
| Langkah 2 | Pindah ke CDN | 5,39 detik |
| Langkah 3 | Konversikan ke format webp / avif | 2,88 detik |
| Langkah 4 | Menambahkan q_auto pengoptimalan kualitas dan gambar responsif dengan <picture> |
2,33 detik |
| Langkah 5 | Pramuat + fetchpriority="high" |
2.30 detik |
| Langkah 6 | Cache CDN diaktifkan | 1,22 detik |
Gambar seringkali menjadi kontributor terbesar yang memperlambat waktu muat aplikasi React, dan gambar juga merupakan salah satu hal yang paling mudah untuk diperbaiki. Dengan langkah-langkah yang diberikan dalam postingan blog ini, Anda dapat mengoptimalkan gambar Anda secara bertahap, dengan fokus pada gambar LCP terlebih dahulu, dan mengamati peningkatan kinerja.
🚀 Mendaftar untuk buletin The Replay
Pemutaran Ulang adalah buletin mingguan untuk para pemimpin pengembang dan teknik.
Disampaikan seminggu sekali, ini adalah panduan pilihan Anda untuk percakapan paling penting seputar pengembangan frontend, alat AI yang sedang berkembang, dan keadaan perangkat lunak modern.
Bersiaplah dengan pelacakan kesalahan React modern LogRocket dalam hitungan menit:
-
Kunjungi untuk mendapatkan ID aplikasi
-
Instal LogRocket melalui npm atau tag skrip.
LogRocket.init()harus disebut sisi klien, bukan sisi server$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');// Add to your HTML: <script src=" <script>window.LogRocket && window.LogRocket.init('app/id');</script> - (Opsional) Instal plugin untuk integrasi lebih dalam dengan tumpukan Anda:
- Perangkat tengah Redux
- Perangkat tengah NgRx
- Plugin Vuex
Mulailah sekarang
PakarPBN
A Private Blog Network (PBN) is a collection of websites that are controlled by a single individual or organization and used primarily to build backlinks to a “money site” in order to influence its ranking in search engines such as Google. The core idea behind a PBN is based on the importance of backlinks in Google’s ranking algorithm. Since Google views backlinks as signals of authority and trust, some website owners attempt to artificially create these signals through a controlled network of sites.
In a typical PBN setup, the owner acquires expired or aged domains that already have existing authority, backlinks, and history. These domains are rebuilt with new content and hosted separately, often using different IP addresses, hosting providers, themes, and ownership details to make them appear unrelated. Within the content published on these sites, links are strategically placed that point to the main website the owner wants to rank higher. By doing this, the owner attempts to pass link equity (also known as “link juice”) from the PBN sites to the target website.
The purpose of a PBN is to give the impression that the target website is naturally earning links from multiple independent sources. If done effectively, this can temporarily improve keyword rankings, increase organic visibility, and drive more traffic from search results.