Belajar Next.js - Performance Optimization
Episode 15 of 24

Belajar Next.js - Performance Optimization

Episode ini membahas profiling dengan React DevTools dan tool browser, code splitting dengan bundle analysis dan tree shaking, optimasi Core Web Vitals, serta pengurangan payload JavaScript memakai server components dan dynamic import.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Optimasi performa bukan soal menebak: butuh pengukuran, diagnosis, lalu perbaikan yang terukur. Di episode 15 kita membangun proses itu dari awal — dari profiling, analisis bundle, metrik Web Vitals, sampai teknik konkret mengurangi JavaScript yang dikirim ke browser.

Profiling dengan React DevTools dan Browser Tools

Mengukur Sebelum Mengoptimasi

Langkah pertama adalah mengukur. React DevTools menampilkan profil rendering: komponen mana yang paling sering di-render dan berapa lama tiap render berlangsung. DevTools browser (Chrome/Edge) menyediakan Performance panel untuk merekam event load, network, dan rendering secara menyeluruh.

Alur yang disarankan: rekam interaksi yang lambat, amati profiler, temukan komponen yang mengonsumsi waktu, lalu perbaiki dan ukur ulang. Tanpa pengukuran awal, kalian hanya mengoptimasi secara acak.

Latih kebiasaan mengukur di setiap milestone: sebelum memulai fitur, catat baseline; setelah selesai, bandingkan hasilnya. Ini membangun budaya performa di tim alih-alih menunggu masalah muncul.

Profil yang baik dimulai dari reproduksi yang stabil: gunakan perangkat yang sama dan catat kondisi jaringan agar perbandingan antar sesi tetap adil.

Beberapa situasi yang sering muncul di profil: komponen yang di-render ulang karena props objek baru dibuat tiap render, event handler inline yang mengubah referensi, dan state yang disimpan terlalu tinggi di pohon komponen. Memoization dengan useMemo dan useCallback membantu, tapi hanya setelah diukur — jangan mengoptimasi tanpa data.

Code Splitting, Bundle Analysis, dan Tree Shaking

Menganalisis Bundle

Next.js sudah melakukan code splitting per route — hanya JavaScript untuk halaman aktif yang dikirim. Untuk memverifikasi, pasang @next/bundle-analyzer dan jalankan build dengan analisis:

Analisis ukuran bundle
npm install --save-dev @next/bundle-analyzer
npx next build --analyze

Perintah npx next build --analyze membuka laporan visual ukuran tiap bundle. Dari sini terlihat library mana yang menyumbang ukuran terbesar — biasanya chart, editor, atau date picker.

Tree Shaking

Tree shaking membuang kode yang tidak terpakai dari bundle. Praktik yang mendukungnya: import bernama dari library daripada import * as, hindari side-effect saat import, dan pilih library yang dirancang tree-shakeable. Bundle analyzer juga mengungkap kode yang seharusnya bisa dipangkas.

Rutinitas yang dianjurkan: jalankan bundle analyzer sebelum dan sesudah menambah dependency baru. Jika sebuah library menambah 50 kB untuk fitur yang jarang dipakai, cari alternatif atau alihkan ke dynamic import.

Selain ukuran per route, perhatikan juga jumlah request: terlalu banyak chunk kecil juga bisa melambatkan. Keseimbangan antara jumlah dan ukuran chunk adalah bagian dari seni optimasi bundle.

Web Vitals dan Core Web Vitals Optimization

Empat Metrik Utama

Core Web Vitals adalah standar pengalaman pengguna yang diukur Google:

  • LCP (Largest Contentful Paint): kecepatan elemen terbesar muncul — target di bawah 2,5 detik.
  • INP (Interaction to Next Paint): responsivitas interaksi — target di bawah 200 milidetik.
  • CLS (Cumulative Layout Shift): stabilitas layout saat elemen bergeser — target di bawah 0,1.
  • TTFB (Time to First Byte): waktu response awal server.

Tiga yang pertama adalah Core Web Vitals; TTFB adalah metrik dukungan yang memengaruhi LCP. Optimasi gambar LCP, dimensi eksplisit untuk mencegah CLS, dan pengurangan JavaScript untuk INP adalah tiga perbaikan dengan dampak terbesar. Skor web vitals juga dipengaruhi infrastruktur: pilih platform dengan edge network dan HTTP/3 untuk memangkas TTFB, terutama untuk pengguna lintas negara.

INP mengukur latensi interaksi pengguna: sejak klik, ketukan, atau scroll, sampai respons terlihat. Penyebab umum INP buruk adalah JavaScript berat yang memblokir main thread. Kurangi pekerjaan utama dengan menyerahkan rendering ke server components dan membatasi update state yang tidak perlu. Sedangkan CLS biasanya berasal dari gambar tanpa dimensi, font yang memuat terlambat, dan iklan yang disisipkan setelah konten.

  • Optimasi font dengan next/font agar teks tidak bergeser saat font dimuat.
  • Hindari import library besar di halaman pertama.
  • Biarkan komponen Image mengelola format WebP dan AVIF secara otomatis.

Memantau dengan reportWebVitals

App Router menyediakan fungsi reportWebVitals untuk mengirim metrik ke layanan analitik:

Memantau Web Vitals di klien
"use client"
 
export function reportWebVitals(metric) {
  console.log(metric.name, metric.value)
}

Fungsi reportWebVitals(metric) dipanggil setiap kali metrik diukur. Kirim nilainya ke endpoint sendiri atau layanan seperti Vercel Analytics — topik observability akan dibahas lengkap di episode 22.

Mengurangi JavaScript Payload

Server Components dan dynamic import

Server components tidak mengirim JavaScript ke browser — memindahkan rendering ke server mengurangi payload secara drastis. Untuk komponen klien yang berat, pakai dynamic import agar hanya dimuat saat dibutuhkan:

Dynamic import dengan next/dynamic
import dynamic from "next/dynamic"
 
const Chart = dynamic(() => import("@/components/Chart"), {
  ssr: false,
  loading: () => <p>Memuat grafik...</p>,
})

dynamic() di atas memisahkan komponen Chart ke bundle tersendiri yang hanya diunduh saat dirender. Opsi ssr: false mencegah komponen berat ikut dirender di server. Strategi ini mencegah seluruh halaman membayar biaya komponen yang jarang terlihat.

Kombinasi server components, dynamic import, dan pembatasan library menghasilkan penurunan payload yang drastis. Target yang sehat: JavaScript di bawah 150 kB per route untuk halaman konten, lebih kecil lebih baik. Ukur dengan bundle analyzer setelah setiap perubahan besar agar tren ukuran tidak memburuk tanpa disadari. Perhatikan juga JSON besar yang diimport langsung dari file — ikut masuk bundle; pindahkan data besar ke API atau buat pipeline yang hanya menyertakan field yang dibutuhkan.

Selain itu, React Compiler yang diadopsi Next.js mengoptimasi memoization secara otomatis sehingga banyak penggunaan useMemo manual menjadi tidak perlu. Fitur ini mengurangi pekerjaan yang harus dijaga developer dan menjadikan optimasi performa lebih sederhana.

Penutup

Inti yang harus dibawa pulang:

  • Ukur dulu dengan profiler sebelum mengoptimasi.
  • Bundle analyzer mengungkap library penyumbang ukuran terbesar.
  • Tree shaking membuang kode yang tidak terpakai.
  • LCP, INP, dan CLS adalah metrik yang wajib dipantau.
  • Server components tidak mengirim JavaScript ke browser.
  • Dynamic import memuat komponen berat hanya saat dibutuhkan.

Di episode 16 selanjutnya kita akan membahas testing dan quality — unit testing dengan Jest dan React Testing Library, integration dan E2E testing dengan Playwright atau Cypress, accessibility testing, serta static analysis dengan ESLint dan type checking. Kualitas aplikasi kalian akan dijamin oleh otomatisasi.

Belajar Next.js - Performance Optimization | Belajar Next.js