Cara dynamic import client only Next.js yang benar adalah memakai next/dynamic dengan opsi ssr: false supaya komponen hanya dimuat dan dirender di browser. Pola ini memecah bundle awal dan mencegah error window is not defined dari library yang membaca window, document, atau localStorage saat render server.
Gunakan next/dynamic dengan ssr false untuk Komponen Client Only
Server Component berjalan di server dan tidak boleh menyentuh browser API. Client Component bisa interaktif, tetapi kode modulnya tetap ikut render server kecuali dimuat dinamis dengan ssr: false.
Gunakan pola ini untuk chart, editor, peta, atau pemutar media yang mengakses DOM saat inisialisasi:
import dynamic from "next/dynamic";
const ChartClient = dynamic(() => import("./ChartClient"), {
ssr: false,
loading: () => <p>Memuat grafik...</p>,
});
Fallback loading menjaga layout tetap stabil saat chunk tambahan diunduh browser.
Langkah Menerapkan Dynamic Import Client Only di App Router
- Buat komponen browser di
ChartClient.tsxdan awali dengan"use client". - Letakkan semua akses
window,canvas, dan event listener di dalam komponen tersebut. - Impor komponen itu dari page memakai
dynamic(..., { ssr: false }). - Tambahkan fallback
loadingagar tidak ada area kosong yang melompat. - Panggil komponen dinamis dari page Server Component seperti biasa.
- Komponen berat yang tidak terlihat saat first paint, misalnya grafik di bawah fold.
- Library browser-only seperti chart, map, rich text editor, dan drag and drop.
- Widget interaktif besar yang hanya dipakai pada kondisi tertentu.
// ChartClient.tsx
"use client";
import { useEffect, useState } from "react";
export default function ChartClient() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <p>Lebar layar: {width}px</p>;
}
// page.tsx
import dynamic from "next/dynamic";
const ChartClient = dynamic(() => import("./ChartClient"), {
ssr: false,
loading: () => <p>Memuat grafik...</p>,
});
export default function Page() {
return (
<main>
<h1>Laporan</h1>
<ChartClient />
</main>
);
}
Tabel Pilihan Pola Load Komponen Client
ssr: false wajib bila modul membaca browser API saat diimpor atau saat render pertama. Bila komponen hanya memakai state dan event tanpa browser API, impor statis biasanya cukup.
| Pola | Fungsi | Catatan |
|---|---|---|
| Import statis | Render server lalu hidrasi | Cocok untuk UI interaktif ringan |
| Dynamic ssr false | Hanya render di browser | Wajib untuk library browser-only |
| Dynamic di Client Component | Split chunk bersyarat | Berguna untuk modal atau tab berat |
Dynamic import memindahkan biaya unduh ke waktu dibutuhkan. Chunk tambahan tetap menambah total request, jadi pakai hanya untuk bagian yang memang berat atau jarang dipakai.
FAQ
Apakah dynamic import butuh use client?
Ya untuk komponen targetnya, karena komponen browser-only harus dideklarasikan sebagai Client Component.
Kenapa tetap error window is not defined?
Periksa impor library browser-only di level modul Server Component atau hilangkan akses window di luar useEffect dan event handler.
Apakah loading fallback wajib diisi?
Tidak wajib, tetapi disarankan agar pengguna tidak melihat layout kosong atau bergeser saat chunk dimuat.