Pengguna menekan tombol kembali lebih sering daripada hampir semua kontrol lainnya di browser. Mereka mengharapkan layar sebelumnya muncul seketika, tepat di posisi terakhir mereka meninggalkannya. Browser modern memenuhi ekspektasi tersebut dengan back/forward cache, atau bfcache. Alih-alih menghancurkan halaman saat Anda berpindah, browser membekukannya di dalam memori. Saat Anda kembali, browser memulihkan sebuah snapshot. Browser melewatkan proses parsing HTML, eksekusi ulang JavaScript, dan kalkulasi ulang tata letak (layout). Hasilnya terasa instan karena halaman tersebut tidak pernah benar-benar mati.
Apa yang sebenarnya dilakukan bfcache
Pemuatan halaman normal itu memakan banyak sumber daya (expensive). Browser harus mengambil sumber daya, melakukan tokenisasi HTML, membangun DOM, menjalankan skrip, menyelesaikan gaya (styles), melakukan tata letak (layout), melukis piksel (paint pixels), dan menyusun lapisan (composite layers). bfcache menghindari hampir semua proses itu dengan menjaga halaman tetap hidup dalam keadaan beku di RAM. Ini bukan disk cache. Halaman yang telah dirender, termasuk JavaScript heap, posisi gulir (scroll position), dan status formulir, tetap berada di memori saat pengguna membaca halaman berikutnya. Saat pengguna mengklik kembali, browser mencairkan snapshot tersebut dan memicu peristiwa pageshow. Halaman berlanjut tanpa menyentuh jaringan atau melakukan tata letak ulang dari awal. Bagi pengguna dengan perangkat lambat atau koneksi yang tidak stabil, perbedaan antara pemulihan bfcache dan pemuatan baru bisa mencapai ratusan milidetik atau lebih.
Apa yang merusaknya
Seorang pengembang baru-baru ini menjalankan eksperimen bersih untuk mengetahui secara pasti apa yang menghalangi bfcache. Mereka membuat enam halaman sederhana, masing-masing menguji satu penghalang yang dicurigai, lalu berpindah halaman dan menekan tombol kembali. Hasilnya sangat jelas.
Halaman dasar tanpa header atau skrip yang tidak biasa berhasil dipulihkan. Halaman dengan listener beforeunload juga pulih tanpa masalah. Mengejutkannya, halaman yang disajikan dengan Cache-Control: no-store juga masuk ke dalam bfcache, yang bertentangan dengan panduan lama. Bahkan artikel blog langsung (live blog), yang mungkin tampak terlalu dinamis untuk dibekukan, berhasil dipulihkan.
Dua halaman gagal. Halaman dengan event listener unload tidak dapat dipulihkan. Halaman dengan koneksi WebSocket yang terbuka juga terblokir. Kedua kegagalan ini menunjukkan jebakan yang menjerat situs produksi nyata setiap hari.
Jebakan peristiwa unload
Peristiwa unload telah lama menjadi sinyal utama untuk pembersihan di detik terakhir. Pengembang menggunakannya untuk mengirimkan analytics beacons, menghentikan timer, atau menghapus status sementara. Masalahnya adalah bfcache dibangun berdasarkan gagasan bahwa halaman tersebut mungkin akan hidup kembali. Jika browser melihat adanya listener unload, browser akan berasumsi bahwa halaman tersebut mengharapkan penghancuran total dan menolak untuk membekukannya. Tidak peduli apakah fungsi yang terpasang itu kosong. Keberadaan listener tersebut saja sudah cukup untuk membatalkan caching di setiap browser modern.
Penggantinya adalah pagehide. Peristiwa ini dipicu baik saat halaman sedang dibekukan untuk bfcache maupun saat halaman benar-benar dibuang. Jika Anda perlu membedakan keduanya, properti event.persisted bernilai true saat halaman menuju ke bfcache. Namun, untuk sebagian besar tugas pembersihan (teardown), pagehide mencakup kedua jalur tersebut. Pindahkan setiap bagian logika pembersihan dari unload ke pagehide. Kemudian hapus seluruh listener unload, termasuk yang tersembunyi di dalam cuplikan (snippet) analitik pihak ketiga atau plugin lama.
Jebakan koneksi aktif
Koneksi jaringan atau penyimpanan yang terbuka menandakan bahwa halaman Anda masih melakukan pekerjaan nyata. Browser mendata sumber daya yang aktif pada saat navigasi. Jika ditemukan WebSocket yang terbuka, koneksi peer WebRTC yang aktif, atau koneksi IndexedDB yang masih tersisa, browser akan membatalkan pembekuan dan menutup halaman secara normal. Snapshot tidak dapat dipercaya selama aliran data (bytes) mungkin masih berlangsung.
Anda harus menutup sumber daya ini di dalam listener pagehide. Panggil metode close pada WebSocket Anda. Matikan koneksi peer WebRTC. Batalkan atau selesaikan (commit) transaksi IndexedDB yang masih tertunda. Jika aplikasi Anda membutuhkan saluran tersebut saat pengguna kembali, buka kembali di dalam pageshow. Pola close-on-pagehide, restore-on-pageshow ini menjaga halaman tetap memenuhi syarat untuk navigasi kembali secara instan tanpa kehilangan fungsionalitas.
Kejutan no-store
Selama bertahun-tahun, anggapan umum menyatakan bahwa Cache-Control: no-store mencegah bfcache. Chrome mengubah perilaku tersebut pada tahun 2025. Halaman yang disajikan dengan no-store kini dapat masuk ke dalam bfcache. Browser hanya akan menghapus snapshot yang dibekukan tersebut kemudian jika status autentikasi atau cookie berubah dengan cara yang membatalkan status yang tersimpan. Jika Anda selama ini menggunakan no-store sebagai
