Aset Statis & Gambar (next/image)
Pelajari cara menyajikan file statis (seperti favicon atau gambar umum) menggunakan folder `public` di Next.js, dan cara mengoptimalkan gambar secara otomatis untuk performa web yang lebih baik menggunakan komponen `<Image>` dari `next/image`.
Dari Favicon Sampe Foto Produk: Ngurusin Aset Statis & Optimasi Gambar di Next.js!
Aplikasi web kita gak cuma soal kode HTML, CSS, dan JavaScript. Seringkali kita butuh nampilin aset statis lain kayak:
- Gambar (logo, ikon, foto produk, ilustrasi)
- Favicon (ikon kecil di tab browser)
- Font kustom (kalau gak pake layanan font web)
- File PDF atau dokumen lain yang mau di-download
Next.js punya cara yang gampang buat ngelola aset statis ini, dan juga punya "jurus sakti" buat ngoptimasi gambar biar website kita loadingnya makin ngebut: yaitu pake komponen <Image>
dari next/image
.
1. Folder public/
: "Gudang" Aset Statis Akses Langsung
Kalau kamu punya file-file yang mau disajiin apa adanya ke browser dan bisa diakses langsung dari URL root websitemu, tempat paling pas buat menyimpannya adalah di dalam folder public/
.
-
Cara Kerja:
- Bikin folder
public
di direktori root proyek Next.js-mu (sejajar samasrc/
atauapp/
kalau kamu pakesrc/
). - Taruh semua aset statismu di dalam folder
public/
ini. Kamu bisa bikin sub-folder di dalamnya buat organisasi (misal,public/images/
,public/fonts/
). - File-file di dalam
public/
bisa diakses langsung dari browser pake URL yang dimulai dari root domainmu, tanpa perlu nyebutinpublic/
di path-nya.- Misalnya, kalau kamu menyimpan
logo.png
dipublic/images/logo.png
, kamu bisa ngaksesnya dihttp://localhost:3000/images/logo.png
(pas development) atauhttps://domainmu.com/images/logo.png
(pas udah di-deploy). - Kalau kamu menyimpan
favicon.ico
dipublic/favicon.ico
, browser otomatis bakal nyari dihttp://domainmu.com/favicon.ico
.
- Misalnya, kalau kamu menyimpan
- Bikin folder
-
Contoh Penggunaan di HTML/JSX:
html <!-- Di src/app/layout.tsx buat favicon --> <head> <link rel="icon" href="/favicon.ico" /> {/* Path-nya langsung dari root, gak pake public/ */} </head> <!-- Di komponen React mana aja --> <img src="/images/banner-promo.jpg" alt="Promo Spesial" /> {/* Asumsi banner-promo.jpg ada di public/images/ */}
-
Kapan Pake
public/
?- Buat file-file yang emang bener-bener statis dan gak perlu diproses sama build system Next.js (kayak favicon, robots.txt, beberapa gambar umum, file font).
- PENTING: Jangan taruh file kode sumber (
.js
,.jsx
,.ts
,.tsx
) atau file yang butuh kompilasi/bundling di sini. Folderpublic/
cuma buat aset yang "disajikan apa adanya".
2. Komponen <Image>
dari next/image
: Jagoan Optimasi Gambar!
Nampilin gambar di web itu gampang pake tag <img>
HTML biasa. Tapi, gambar itu sering jadi biang keladi website jadi lemot kalau ukurannya gede banget atau gak dioptimasi.
Nah, Next.js nyediain komponen <Image>
(diimpor dari next/image
) yang udah punya fitur optimasi gambar otomatis "out-of-the-box". Pake komponen ini sangat direkomendasiin daripada <img>
biasa buat sebagian besar kasus.
-
Kenapa Pake
<Image>
? Manfaatnya Apa Aja?- Optimasi Ukuran Otomatis: Next.js bisa otomatis nge-resize, ngompres, dan bahkan ngubah format gambar (misal, ke WebP yang lebih modern dan efisien) biar ukurannya jadi lebih kecil tanpa ngorbanin kualitas visual terlalu banyak. Ini dilakuin pas proses build atau on-demand di server.
- Lazy Loading Bawaan: Gambar baru bakal di-load sama browser pas dia udah mau deket atau masuk ke viewport (area yang keliatan di layar). Ini ningkatin performa loading awal halaman banget, apalagi kalau halamannya banyak gambar.
- Mencegah Layout Shift: Kamu wajib ngasih tau ukuran gambar (
width
danheight
props, atau pakefill
prop). Ini ngebantu Next.js "nyiapin tempat" buat gambar sebelum dia ke-load, jadi layout halaman gak "loncat-loncat" pas gambar muncul (ini bagus buat Core Web Vitals). - Menyajikan Ukuran Gambar yang Sesuai untuk Berbagai Perangkat (Responsive Images): Dengan prop
sizes
, kamu bisa ngasih hint ke browser buat milih versi gambar yang ukurannya paling pas buat layar pengguna. - Dukungan Gambar Lokal dan Eksternal (Remote): Bisa buat gambar yang ada di folder
public/
atausrc/
(diimpor), bisa juga buat gambar dari URL eksternal (tapi butuh sedikit konfigurasi dinext.config.mjs
buat domain remote-nya).
-
Cara Pake
<Image>
Dasar:- Impor:
import Image from 'next/image';
- Gunakan di JSX:
tsx import Image from 'next/image'; import gambarProfil from '@/assets/profil-saya.jpg'; // Contoh impor gambar lokal dari src/assets/ function KartuProfil() { return ( <div> {/* Contoh 1: Gambar Lokal yang Diimpor (Ukuran diketahui) */} <Image src={gambarProfil} // Objek gambar hasil impor alt="Foto Profil Saya" width={150} // WAJIB kalau src itu objek impor height={150} // WAJIB kalau src itu objek impor // priority // Tambahin ini kalau gambarnya penting & di atas lipatan (above-the-fold) className="rounded-full" // Bisa di-style pake Tailwind atau CSS biasa /> {/* Contoh 2: Gambar dari Folder public/ (Ukuran harus diset) */} <Image src="/images/logo-perusahaan.png" // Path relatif ke folder public alt="Logo Perusahaan" width={200} height={50} // style={{ objectFit: 'contain' }} // Bisa juga pake style inline buat object-fit /> {/* Contoh 3: Gambar Remote (Domainnya harus di-whitelist di next.config.mjs) */} {/* <Image src="https://images.unsplash.com/photo-12345" alt="Gambar dari Unsplash" width={500} height={300} /> */} </div> ); }
- Props Penting:
src
: Sumber gambar. Bisa berupa:- Objek gambar hasil impor statis (kayak
gambarProfil
di atas). Next.js otomatis tauwidth
danheight
-nya. - String path ke gambar di folder
public/
(diawali/
). Di sini kamu wajib ngasih propwidth
danheight
. - String URL lengkap ke gambar eksternal. Di sini juga wajib ngasih
width
danheight
, dan domainnya harus didaftarin dinext.config.mjs
.
- Objek gambar hasil impor statis (kayak
alt
: Teks alternatif (WAJIB buat aksesibilitas!).width
: Lebar gambar dalam pixel (bukan string, tapi angka).height
: Tinggi gambar dalam pixel.fill
(Boolean): Kalautrue
, gambar bakal ngisi penuh elemen parent-nya. Parent-nya harus punyaposition: relative;
(ataufixed
/absolute
) dan punya ukuran (width/height) atau rasio aspek yang jelas. Kalau pakefill
, kamu gak perlu (dan gak boleh) ngasihwidth
&height
ke<Image>
. Sering dipake barengstyle={{ objectFit: 'cover' }}
ataustyle={{ objectFit: 'contain' }}
atauclassName
yang ngaturobject-fit
.tsx <div className="relative w-full h-64"> {/* Parent punya ukuran dan position relative */} <Image src="/images/hero.jpg" alt="Hero Banner" fill style={{ objectFit: 'cover' }} /> </div>
sizes
(String): Ngasih hint ke browser soal ukuran gambar yang bakal dirender di berbagai ukuran viewport (buat optimasi gambar responsif). Formatnya mirip atributsizes
di tag<img>
HTML. Contoh:"(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
. Ini ngebantu Next.js milih source gambar yang paling pas.priority
(Boolean): Kalautrue
, Next.js bakal ngasih prioritas lebih buat nge-load gambar ini (misal, gak di-lazy load, nambahin preload link). Pake ini buat gambar penting yang ada di above-the-fold (bagian halaman yang langsung keliatan tanpa scroll), kayak gambar hero banner.quality
(Number 1-100): Ngatur kualitas gambar hasil optimasi (default 75).
- Impor:
-
Konfigurasi Domain Gambar Remote: Kalau mau pake gambar dari URL eksternal (misal, dari Unsplash, CMS, atau CDN lain), kamu harus ngasih tau Next.js domain mana aja yang diizinin. Ini buat keamanan. Buka file
next.config.mjs
(atau.js
) di root proyekmu, terus tambahin konfigurasiimages
:javascript // next.config.mjs /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, images: { remotePatterns: [ { protocol: 'https', hostname: 'images.unsplash.com', // port: '', // Opsional // pathname: '/account123/**', // Opsional, kalau mau lebih spesifik path-nya }, { protocol: 'https', hostname: 'cdn.another-domain.com', }, // Tambahin domain lain di sini kalau perlu ], // Kamu juga bisa pake 'domains' (array of strings) buat kasus simpel, // tapi 'remotePatterns' lebih fleksibel dan aman. // domains: ['images.unsplash.com', 'cdn.another-domain.com'], }, }; export default nextConfig;
Setelah ngubah
next.config.mjs
, kamu perlu restart development server-mu.
Impor Gambar Lokal dari src/
(atau app/
)
Selain dari folder public/
, kamu juga bisa ngimpor file gambar langsung ke dalam komponenmu kalau gambarnya ada di dalam src/
(atau app/
).
// src/app/components/LogoSaya.tsx
import Image from 'next/image';
import logoMahirDev from '@/assets/logo-mahirdev.png'; // Asumsi gambar ada di src/assets/
export default function LogoSaya() {
return (
<Image
src={logoMahirDev} // Objek gambar hasil impor
alt="Logo Mahir.dev"
width={150} // Next.js bisa otomatis tau ukuran gambar lokal, tapi tetep bagus ditulis
height={50}
// priority // Kalau ini logo utama di header, mungkin perlu priority
/>
);
}
Pas kamu impor gambar kayak gini, Next.js (via build tool kayak Webpack/Turbopack) bakal ngurusin gambar itu, ngasih hash unik ke namanya, dan ngopi ke folder build. Variabel logoMahirDev
bakal jadi objek yang isinya info soal gambar itu (termasuk src
, width
, height
). Ini cara yang bagus buat aset yang emang jadi bagian dari komponenmu.
Ngurusin aset statis dan terutama gambar itu penting banget buat performa dan tampilan website. Folder public/
itu gampang buat file-file yang "apa adanya". Tapi buat gambar, sangat disarankan buat selalu pake komponen <Image>
dari next/image
karena optimasi otomatisnya bakal ngebantu banget ningkatin kecepatan loading dan skor Core Web Vitals websitemu.
Awalnya mungkin props <Image>
keliatan banyak, tapi kalau udah biasa, kamu bakal ngerasain manfaatnya!