ClientRouter & transisi halaman
ClientRouter memberi portal beritamu transisi halus antar artikel. Ia juga mengubah asumsi dasar setiap skrip di halamanmu, dan iklan adalah korban pertamanya.
Intisari
<ClientRouter />di<head>layout membuat navigasi jadi swap DOM, bukan muat ulang penuh.- Namanya bukan
<ViewTransitions />lagi โ itu dihapus di Astro 6. <script>biasa tidak dijalankan ulang setelah navigasi. Ini penyebab iklan dan analitik mati.- Pakai event
astro:page-loaduntuk kode yang harus jalan di tiap halaman. - Untuk portal berita yang hidup dari iklan, ukur untung-ruginya sebelum menyalakan ini.
Memasangnya
---
// src/layouts/Dasar.astro
import { ClientRouter } from "astro:transitions";
---
<head>
โฆ
<ClientRouter />
</head>
Setelah ini, klik tautan internal tidak lagi memuat ulang dokumen. Astro mengambil halaman tujuan,
menukar isi <body>, dan menganimasikan transisinya lewat View Transitions API browser.
Kalau tutorial menyuruhmu memakai <ViewTransitions />, tutorial itu ditulis untuk
Astro 4 ke bawah. Komponen itu diganti nama jadi <ClientRouter /> dan versi lamanya
dihapus di Astro 6.
Transisi bernama
<!-- Di kartu artikel pada halaman daftar -->
<img src={a.gambar} transition:name={`sampul-${a.id}`} />
<h2 transition:name={`judul-${a.id}`}>{a.judul}</h2>
<!-- Di halaman artikel -->
<img src={artikel.gambar} transition:name={`sampul-${artikel.id}`} />
<h1 transition:name={`judul-${artikel.id}`}>{artikel.judul}</h1>
Nama yang sama di dua halaman membuat browser menganimasikan elemen itu dari posisi lama ke posisi baru. Untuk portal berita, gambar sampul yang membesar mulus dari kartu ke halaman artikel adalah efek yang terasa mahal dan biayanya nol JavaScript tambahan.
transition:name harus unik dalam satu halaman. Kalau dua kartu memakai nama yang
sama, browser tidak tahu mana yang harus dianimasikan dan transisinya berhenti bekerja โ diam saja,
tanpa error. Selalu sertakan ID.
Harga yang harus dibayar
1. Skrip tidak dijalankan ulang
<script>
// Jalan SEKALI, saat pertama kali dokumen dimuat.
// Setelah navigasi ClientRouter, TIDAK jalan lagi.
document.querySelectorAll(".tab").forEach(pasangHandler);
</script>
<script>
// Jalan di tiap halaman, termasuk yang pertama.
document.addEventListener("astro:page-load", () => {
document.querySelectorAll(".tab").forEach(pasangHandler);
});
</script>
2. Skrip pihak ketiga adalah korban utama
| Skrip | Yang terjadi | Perbaikan |
|---|---|---|
| Google Analytics / GA4 | Pageview hanya tercatat sekali | Kirim page_view manual di astro:page-load |
| Google Tag Manager | Trigger halaman tidak menyala lagi | Push ke dataLayer di astro:page-load |
| Google AdSense / GAM | Iklan tidak dimuat ulang | Panggil ulang googletag.pubads().refresh() |
| Embed Twitter / Instagram | Tetap jadi tautan mentah | twttr.widgets.load() di astro:page-load |
| Komentar pihak ketiga | Widget tidak muncul di artikel kedua | Inisialisasi ulang |
Baris iklan itu bukan gangguan kecil untuk portal berita โ itu pendapatan. Pembaca yang membuka lima artikel berturut-turut hanya menghasilkan satu tayangan iklan alih-alih lima, dan penurunannya tidak akan tampak sebagai error di mana pun. Ia hanya muncul sebagai angka pendapatan yang turun bulan berikutnya. Kalau portalmu bergantung pada iklan tayangan, ukur dulu di sebagian trafik sebelum menyalakan ClientRouter untuk semua orang.
<script>
document.addEventListener("astro:page-load", () => {
// GA4
(window as any).gtag?.("event", "page_view", {
page_path: location.pathname,
page_title: document.title,
});
// Iklan โ segarkan slot untuk halaman baru
(window as any).googletag?.cmd.push(() => {
(window as any).googletag.pubads().refresh();
});
});
</script>
3. Kebocoran memori
// Di island Vue: bersihkan apa pun yang kamu pasang di luar komponen
onUnmounted(() => {
chart.value?.destroy();
observer?.disconnect();
clearInterval(timer);
});
Tanpa ClientRouter, muat ulang halaman membersihkan segalanya secara paksa โ jadi listener yang bocor tidak pernah terasa. Dengan ClientRouter, dokumen yang sama hidup terus, dan setiap navigasi menambah satu listener lagi. Setelah dua puluh artikel, ponsel pembaca melambat.
Daftar event
| Event | Kapan | Pakai untuk |
|---|---|---|
astro:before-preparation | Navigasi dimulai | Menampilkan indikator memuat |
astro:after-preparation | Halaman baru siap | Menyembunyikan indikator |
astro:before-swap | Sebelum DOM ditukar | Menyimpan posisi gulir, membersihkan |
astro:after-swap | Setelah DOM ditukar | Memulihkan tema sebelum ia berkedip |
astro:page-load | Halaman siap, termasuk yang pertama | Yang paling sering kamu butuhkan |
Mempertahankan elemen antar halaman
<!-- Pemutar audio tetap hidup saat pembaca pindah artikel -->
<audio transition:persist id="pemutar" controls></audio>
<!-- Header tidak ikut dianimasikan keluar-masuk -->
<header transition:persist>โฆ</header>
Ini fitur yang tidak bisa ditiru MPA biasa: pemutar audio berita yang terus berjalan saat pembaca menjelajah artikel lain. Kalau portalmu punya konten audio atau video, ini alasan terkuat menyalakan ClientRouter.
Hormati preferensi pembaca
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
animation: none !important;
}
}
Sebagian orang mengalami mual atau pusing karena animasi transisi. Astro sudah menghormati preferensi ini untuk animasi bawaannya, tapi transisi kustom yang kamu tulis sendiri tidak otomatis ikut.
Haruskah kamu memakainya?
| Nyalakan kalau | Tunda kalau |
|---|---|
| Pembaca membuka banyak artikel per sesi | Pendapatan iklan tayangan dominan |
| Ada media yang harus terus berjalan | Banyak skrip pihak ketiga yang tidak kamu kendalikan |
| Kamu mengendalikan semua skrip di halaman | Tim analitik belum siap menyesuaikan pelacakan |
Latihan: pasang <ClientRouter /> dan transisi bernama untuk gambar sampul dari
daftar ke halaman artikel. Lalu buktikan masalahnya: pasang <script>console.log("halaman")</script>
biasa, navigasi tiga kali, dan hitung berapa kali ia tercetak. Perbaiki dengan
astro:page-load dan hitung lagi.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.