Server Components — React

Sejak 2013-2023, paradigma React = client-side rendering (CSR): HTML kosong, browser download bundle JS, JS yang render UI + fetch data. Hasilnya: bundle gede…

Server Component adalah komponen React yang jalan cuma di server: hasil render-nya dikirim ke browser, kodenya gak pernah. Komponen yang tetap jalan di browser, untuk bagian yang interaktif, disebut Client Component. React 19 menyediakan keduanya, tapi kamu memakainya lewat framework yang mengurus server-nya, paling sering Next.js dengan App Router. Bayangin restoran. Dapur (server) memasak, dan yang sampai ke mejamu adalah makanan jadi, bukan resep dan kompornya. Cuma yang memang dikerjakan di meja, misalnya sambal yang kamu tuang sendiri, dibawakan alatnya. Dapur juga boleh membuka gudang bahan, misalnya database dan kunci rahasia, yang gak pernah dilihat tamu.

🧪 Tebakan cepat: halaman produk berisi nama, harga, deskripsi yang dirender dengan library markdown 36 KB, dan satu tombol +1. Kalau cuma tombolnya yang jadi Client Component, kode komponen apa yang dikirim ke browser? Tebak dulu, jawabannya ada di bagian "Apa yang dikirim ke browser".

Server Component: default, dan boleh async

// app/produk/page.tsx: Server Component (gak ada "use client")
import { db } from "@/lib/db" // contoh library database
import Deskripsi from "./Deskripsi"
import Counter from "./Counter"

export default async function ProdukPage() {
  const produk = await db.produk.findFirst() // langsung ke database

  return (
    <main>
      <h1>{produk.nama}</h1>
      <p>Rp{produk.harga}</p>
      <Deskripsi teks={produk.deskripsi} />
      <Counter />
    </main>
  )
}

Client Component: "use client" di baris pertama

// app/produk/Counter.tsx: Client Component
"use client"

import { useState } from "react"

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p id="count">{count}</p>
      <button id="increment" onClick={() => setCount(count + 1)}>+1</button>
    </div>
  )
}

Apa yang dikirim ke browser

Dengan pembagian tadi, browser menerima tiga hal:

  1. HTML halaman yang sudah jadi: nama, harga, deskripsi, tombol, angka 0.
  2. RSC payload: hasil render Server Component dalam format React, ditambah catatan "di sini ada Counter, ini props-nya".
  3. JavaScript: runtime React dan Next.js, lalu kode Counter saja.

Itu jawaban tebakannya: dari semua komponen di halaman itu, cuma kode Counter yang dikirim. ProdukPage, Deskripsi, dan library markdown-nya tinggal di server. Ini angka contoh yang sama dengan di Lab (ukuran sesudah dikompres gzip):

"use client" ditaruh di JavaScript yang dikirim
Counter saja runtime 100 KB + Counter 1 KB = 101 KB
Deskripsi dan Counter 100 + 1 + Deskripsi 1 + library markdown 36 = 138 KB
ProdukPage (paling atas) gagal: komponen async dan akses database gak bisa jalan di browser

Deskripsi gak interaktif, jadi menjadikannya Client Component cuma menambah 37 KB yang harus diunduh dan dijalankan tiap pengunjung, tanpa ada yang bisa diklik.

Menggabungkan: server di luar, client sekecil mungkin

⚠️ Jebakan yang sering ketemu

TL;DR: Server Component jalan cuma di server: boleh async/await, boleh langsung ke database dan memakai secret, tapi gak boleh state, effect, event handler, atau API browser. Hasil render-nya yang dikirim, kodenya gak. Client Component ditandai "use client" di baris pertama file; kodenya ikut dikirim ke browser supaya useState dan onClick jalan. Di Next.js App Router, komponen adalah Server Component secara default. Taruh "use client" serendah mungkin, kirim props yang bisa diserialisasi, dan JavaScript yang diunduh pengunjung tetap kecil: di contoh ini 101 KB, bukan 138 KB.

Yang akan kamu pelajari