Tips & Tricks (Diperbarui: 2/6/2026)

Code Splitting dan Lazy Loading dengan Claude Code

Terapkan code splitting React/Next.js dengan Claude Code: contoh, langkah, jebakan, verifikasi, dan CTA.

Code Splitting dan Lazy Loading dengan Claude Code

Saat aplikasi React atau Next.js terasa lambat, penyebabnya sering ada pada JavaScript awal yang terlalu besar. Pengunjung hanya ingin membaca halaman atau menekan CTA, tetapi browser ikut mengunduh panel admin, editor, grafik, dan widget yang belum diperlukan.

Code splitting berarti membagi JavaScript menjadi file kecil bernama chunk. Lazy loading berarti chunk tersebut baru dimuat saat benar-benar dibutuhkan. Tujuannya bukan membuat semua hal tertunda, tetapi menjaga layar pertama tetap ringan.

Artikel ini menunjukkan cara memberi tugas yang jelas kepada Claude Code: React.lazy, Suspense, dynamic import(), next/dynamic, pemisahan route/page, risiko hydration, dan checklist verifikasi. Untuk alur performa yang lebih lengkap, baca juga bundle analysis, tree shaking, dan performance optimization.

Istilah dasar

bundle adalah paket JavaScript yang dikirim ke browser. chunk adalah file kecil hasil pemisahan. dynamic import, seperti import("./Chart"), memuat modul saat runtime. Suspense adalah boundary React yang menampilkan fallback ketika komponen lazy sedang dimuat.

hydration adalah proses ketika JavaScript client memasang event dan state ke HTML yang sudah dirender server. Jika output server dan client berbeda, muncul hydration error. Risiko umum datang dari membaca window, localStorage, waktu saat ini, atau nilai acak terlalu awal.

KandidatAlasan cocokPerhatian
Panel adminTidak dibuka semua pengunjungState izin dan loading harus jelas
Grafik, peta, editorDependensi biasanya beratSiapkan tinggi agar layout tidak melompat
Modal dan wizardDibutuhkan setelah aksiPrefetch jika klik pertama terasa lambat
Video, audio, pencarianSering berada di bawah foldAksesibilitas dan pesan error

Beri batasan ke Claude Code

Jangan hanya meminta “lakukan code splitting”. Tuliskan tujuan, file target, area yang tidak boleh rusak, dan cara verifikasi.

Goal:
- Lazy-load UI berat yang tidak dibutuhkan pada layar pertama.
- Jangan pindahkan hero, artikel, navigasi, atau CTA ke balik lazy loading.
- Gunakan React.lazy/Suspense atau next/dynamic sesuai framework.

Targets:
- src/features/reports/ReportsPanel.tsx
- src/features/editor/RichEditor.tsx
- app/admin/page.tsx

Verification:
- npm run lint
- npm run build
- Cek initial JS dan lazy chunks di tab Network.
- Cek tampilan mobile agar fallback tidak menutup CTA.

Dengan scope seperti ini, Claude Code lebih kecil kemungkinannya memecah komponen yang justru penting untuk SEO dan konversi.

React.lazy dan Suspense

Dokumentasi React menjelaskan bahwa lazy menunda pemuatan kode komponen sampai komponen pertama kali dirender. Suspense menampilkan fallback selama proses itu. Deklarasikan komponen lazy di level module, bukan di dalam komponen lain.

// src/App.tsx
import { Suspense, lazy, useState } from "react";

const ReportsPanel = lazy(() => import("./ReportsPanel"));

function PanelSkeleton() {
  return (
    <div role="status" aria-live="polite" style={{ minHeight: 180 }}>
      Memuat laporan...
    </div>
  );
}

export default function App() {
  const [showReports, setShowReports] = useState(false);

  return (
    <main>
      <h1>Dashboard</h1>
      <button type="button" onClick={() => setShowReports(true)}>
        Tampilkan laporan
      </button>

      {showReports ? (
        <Suspense fallback={<PanelSkeleton />}>
          <ReportsPanel />
        </Suspense>
      ) : (
        <p>UI laporan yang berat baru dimuat saat diperlukan.</p>
      )}
    </main>
  );
}
// src/ReportsPanel.tsx
const rows = [
  { label: "Artikel selesai dibaca", value: "68%" },
  { label: "Klik CTA", value: "4.2%" },
  { label: "Kunjungan konsultasi", value: "1.1%" },
];

export default function ReportsPanel() {
  return (
    <section aria-label="Laporan">
      <h2>Laporan konversi</h2>
      <ul>
        {rows.map((row) => (
          <li key={row.label}>
            {row.label}: {row.value}
          </li>
        ))}
      </ul>
    </section>
  );
}

lazy mengharapkan default export. Jika modul hanya punya named export, bungkus hasil import-nya.

// src/lazyNamed.tsx
import { lazy, type ComponentType } from "react";

export function lazyNamed<TModule, TName extends keyof TModule>(
  loader: () => Promise<TModule>,
  name: TName
) {
  return lazy(async () => {
    const module = await loader();
    return {
      default: module[name] as ComponentType,
    };
  });
}
// src/AnalyticsSlot.tsx
import { Suspense } from "react";
import { lazyNamed } from "./lazyNamed";

const BarChart = lazyNamed(() => import("./charts"), "BarChart");

export function AnalyticsSlot() {
  return (
    <Suspense fallback={<p>Memuat grafik...</p>}>
      <BarChart />
    </Suspense>
  );
}

Dynamic import di Next.js

Next.js sudah memisahkan kode berdasarkan pages dan routes. Gunakan next/dynamic ketika sebuah Client Component berat atau bergantung pada API browser. Letakkan import() di dalam dynamic() dan deklarasikan di level module.

// app/admin/EditorSlot.tsx
"use client";

import dynamic from "next/dynamic";

const RichEditor = dynamic(() => import("./RichEditor"), {
  ssr: false,
  loading: () => (
    <p aria-live="polite" style={{ minHeight: 160 }}>
      Memuat editor...
    </p>
  ),
});

export default function EditorSlot() {
  return <RichEditor initialMarkdown="# Draft" />;
}
// app/admin/page.tsx
import EditorSlot from "./EditorSlot";

export default function AdminPage() {
  return (
    <main>
      <h1>Editor artikel</h1>
      <p>Teks dan CTA muncul lebih dulu. Hanya editor berat yang ditunda.</p>
      <EditorSlot />
    </main>
  );
}

ssr: false cocok untuk editor browser-only, tetapi tidak cocok untuk artikel, harga, FAQ, atau CTA utama. Konten seperti itu harus terlihat dalam HTML server.

Pemisahan route dan page

Mulai dari batas route sebelum memecah komponen kecil. Di Next.js, file seperti app/reports/page.tsx dan app/settings/page.tsx sudah menjadi batas alami. Di React Router, route component bisa dibuat lazy.

// src/AppRouter.tsx
import { Suspense, lazy } from "react";
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";

const HomePage = lazy(() => import("./pages/HomePage"));
const ReportsPage = lazy(() => import("./pages/ReportsPage"));
const SettingsPage = lazy(() => import("./pages/SettingsPage"));

function RouteFallback() {
  return <p aria-live="polite">Memuat halaman...</p>;
}

export default function AppRouter() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/reports">Reports</Link>
        <Link to="/settings">Settings</Link>
      </nav>
      <Suspense fallback={<RouteFallback />}>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/reports" element={<ReportsPage />} />
          <Route path="/settings" element={<SettingsPage />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

Jangan membungkus seluruh landing page dalam satu Suspense besar. Judul, value proposition, dan CTA harus tetap muncul cepat.

Use case praktis

Pertama, dashboard SaaS. Shell dan navigasi muncul segera, sedangkan analytics admin, audit log, export CSV, dan chart library dimuat setelah role check.

Kedua, platform editorial atau kursus. Artikel, judul pelajaran, dan CTA pembelian harus render lebih dulu. Markdown editor, image cropper, dan preview pane bisa ditunda.

Ketiga, landing page dengan peta, video, kalkulator, atau grafik. Pesan utama muncul cepat, widget berat dimuat setelah scroll atau klik. Untuk media UI, lihat video player dan accessibility.

Keempat, modal penawaran atau checkout wizard. Tombol langsung tersedia, sedangkan form multi-step dimuat saat diperlukan.

Jebakan umum

  1. Terlalu banyak splitting membuat request kecil bertambah dan interaksi terasa lambat.
  2. Mendeklarasikan lazy atau dynamic di dalam komponen bisa mereset state.
  3. Fallback tanpa tinggi tetap menyebabkan layout shift dan bisa menutup CTA.
  4. Hydration mismatch terjadi ketika server dan client merender output berbeda.
  5. Konten SEO atau monetisasi tidak sebaiknya disembunyikan di balik ssr: false.

Verifikasi

Claude Code review request:
- Pastikan lazy/dynamic dideklarasikan di level module.
- Cek default export vs named export.
- Cek apakah boundary Suspense terlalu luas.
- Pastikan ssr:false tidak menyembunyikan copy SEO atau CTA.
- Cari risiko window/date/random/localStorage.
- Jelaskan cara membandingkan initial JS, lazy chunks, dan jumlah request.
npm run lint
npm run build

Buka DevTools, filter Network ke JS, lalu reload. Chunk editor atau admin tidak boleh muncul pada initial load. Setelah report, editor, atau modal dibuka, chunk terkait baru muncul.

Rujukan resmi: React lazy, React Suspense, Next.js Lazy Loading, dan Next.js Layouts and Pages.

Untuk workflow Claude Code yang berulang, mulai dari free Claude Code cheatsheet. Untuk prompt implementasi dan review yang bisa dipakai ulang, gunakan 50 Claude Code Prompt Templates. Untuk tim yang perlu aturan repo, CLAUDE.md, dan review performa, gunakan training dan konsultasi.

Catatan praktik

Hasil paling stabil muncul ketika konten yang harus dilindungi diputuskan sejak awal: first-screen copy, navigasi, dan CTA tetap server-rendered; laporan dan editor pindah ke lazy chunks. Permintaan samar seperti “buat lazy” cenderung menghasilkan Suspense terlalu luas dan ssr: false yang tidak perlu.

#Claude Code #code splitting #performance #React #Next.js
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.