Direktif hidrasi & anggaran JavaScript
Direktif hidrasi adalah tempat kamu membelanjakan JavaScript. Di portal berita yang hidup dari Core Web Vitals, tiap pilihan di sini terlihat di angka.
Intisari
client:visibleadalah default yang benar untuk hampir semua hal di portal berita.client:loadhanya untuk yang harus interaktif sebelum pembaca menggulir โ biasanya cuma header.client:onlymelewati render server: isinya tidak ada di HTML dan tidak terindeks.client:mediamencegah komponen desktop terunduh di ponsel sama sekali.- Anggaran JS harus jadi angka yang gagal di CI, bukan niat baik.
Lima direktif
| Direktif | JS diunduh | Dirender di server | Pakai untuk |
|---|---|---|---|
client:load | Segera, prioritas tinggi | Ya | Menu akun di header |
client:idle | Saat browser senggang | Ya | Widget kurs, tombol berbagi |
client:visible | Saat masuk viewport | Ya | Default โ tabel, grafik, komentar |
client:media="โฆ" | Kalau media query cocok | Ya | Komponen khusus desktop |
client:only="vue" | Segera | Tidak | Komponen yang butuh window saat inisialisasi |
Peta untuk halaman artikelmu
<!-- Header: harus bisa diklik segera -->
<MenuAkun client:load />
<!-- Tombol berbagi: penting, tapi tidak mendesak -->
<TombolBerbagi client:idle judul={artikel.judul} />
<!-- Grafik di tengah artikel: hanya kalau pembaca sampai ke sana -->
<GrafikSaham client:visible kode={artikel.kodeEmiten} />
<!-- Sidebar analitik: tidak ada di ponsel, jangan diunduh -->
<PanelAnalitik client:media="(min-width: 1024px)" />
<!-- Komentar: paling bawah, paling berat -->
<Komentar client:visible artikelId={artikel.id} />
client:media paling kurang dimanfaatkan orang. Mayoritas pembaca portal berita
Indonesia memakai ponsel di jaringan seluler. Komponen sidebar desktop yang tetap terunduh di ponsel
adalah pemborosan murni โ bukan hanya bandwidth, tapi juga waktu parsing JavaScript di prosesor yang
jauh lebih lambat. Satu atribut menghapusnya sepenuhnya.
client:only dan biayanya
<!-- Isi komponen ini TIDAK ADA di HTML sama sekali -->
<PetaInteraktif client:only="vue" />
| Akibat | Untuk portal berita |
|---|---|
| Tidak terbaca crawler | Serius. Jangan taruh isi artikel di sini |
| Ada jeda kosong sebelum muncul | Menaikkan CLS kalau tidak diberi tinggi tetap |
| Pembaca tanpa JS tidak melihat apa pun | Sediakan fallback yang masuk akal |
| Bundel framework tetap diunduh | Tidak ada penghematan JS dibanding client:load |
Pakai hanya kalau komponennya benar-benar tidak bisa dirender di server โ biasanya karena ia menyentuh
window, document, atau localStorage saat setup. Sering kali
perbaikannya adalah memindahkan akses itu ke onMounted, dan setelah itu
client:visible bekerja dengan baik.
Anggaran JavaScript sebagai angka
"Kirim JavaScript sesedikit mungkin" bukan aturan yang bisa ditegakkan. Angka bisa.
| Halaman | Anggaran JS (terkompresi) | Isinya |
|---|---|---|
| Artikel | โค 45 KB | Vue runtime + menu akun + berbagi |
| Beranda | โค 60 KB | Ditambah widget kurs |
| Data perusahaan | โค 140 KB | Ditambah tabel & grafik |
| Dashboard member | โค 180 KB | Boleh lebih โ di balik login, bukan jalur SEO |
# Ukur setelah build
pnpm build
find dist/client/_astro -name '*.js' -exec sh -c \
'printf "%8s %s\n" "$(gzip -c "$1" | wc -c)" "$1"' _ {} \; | sort -rn | head -20
Jadikan ini gagal di CI, bukan catatan di wiki. Anggaran yang tidak ditegakkan otomatis akan dilanggar dalam tiga bulan โ bukan karena ada yang ceroboh, tapi karena tiap penambahan kecil terlihat wajar sendirian. Skrip sederhana yang menjumlahkan ukuran gzip dan keluar dengan status 1 saat melewati ambang sudah cukup.
Vue runtime dibagi antar island
Kabar baiknya: kalau ada tiga island Vue di satu halaman, runtime Vue-nya diunduh sekali. Astro membundelnya sebagai chunk bersama. Yang bertambah per island hanya kode komponennya sendiri.
Konsekuensinya untuk keputusan arsitektur: island Vue kedua di halaman yang sama jauh lebih murah daripada
yang pertama. Kalau kamu sudah membayar runtime-nya, memakai Vue lagi untuk hal kecil di halaman yang sama
masuk akal. Sebaliknya, memakai Vue untuk satu tombol di halaman yang tidak punya island lain adalah harga
yang mahal โ pakai <script> biasa.
Jangan hidrasi apa yang tidak perlu
| Kebutuhan | Butuh island? | Alternatif |
|---|---|---|
| Akordeon buka/tutup | Tidak | <details> bawaan HTML |
| Tab | Tidak | Anchor + CSS :target, atau tautan biasa |
| Menu dropdown | Tidak | <details> atau Popover API |
| Salin tautan | Tidak | <script> tiga baris |
| Menutup banner | Tidak | <script> + localStorage |
| Tabel dengan sort & filter | Ya | โ |
| Grafik interaktif | Ya | โ |
| Form multi-langkah | Ya | โ |
Enam baris pertama itu yang paling sering jadi island tanpa alasan. Setiap satu yang kamu hindari adalah kilobyte yang tidak pernah diunduh siapa pun.
Latihan: ambil satu halaman artikel di portalmu dan daftarkan setiap elemen interaktif di dalamnya. Untuk masing-masing, tentukan direktifnya โ atau putuskan bahwa ia tidak butuh JavaScript sama sekali. Lalu jalankan skrip pengukur ukuran di atas pada build-mu, dan bandingkan totalnya dengan angka yang kamu catat di Fase 0 untuk versi CI3-nya.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.