Perintah dan konteks
Halaman tersebut berisi navigasi, konten artikel, rekomendasi, komentar, dan tindakan yang dipersonalisasi. Artikel harus terlihat dengan cepat; modul yang lambat tidak boleh memblokir byte pertama atau merusak seluruh halaman ketika satu layanan gagal. Rancang SSR streaming dengan Suspense dan jelaskan bagaimana server mengirimkan shell, bagaimana batasan diselesaikan, bagaimana degradasi kegagalan ditangani, dan bagaimana klien pulih setelah skrip dimuat.
Dokumentasi React menyatakan bahwa streaming dapat mengirimkan shell dan fallback terlebih dahulu, lalu menggantinya saat batasan selesai dimuat. Wawancara ini menguji apakah Anda dapat mengubah mekanisme tersebut menjadi perilaku timeout, penanganan error, cache, dan pemantauan yang terkontrol.
Hal yang dievaluasi pewawancara
Cakup shell yang stabil versus batasan asinkron, deduplikasi permintaan, timeout batasan, error server, percobaan ulang klien, varian cache, pembatalan, aksesibilitas, dan Core Web Vitals. Nyatakan konten mana yang harus sinkron dan mana yang dapat ditunda.
Pertanyaan klarifikasi yang perlu diajukan
- Apakah target layar pertama adalah TTFB, LCP, atau waktu hingga interaktivitas, dan berapa anggaran untuk masing-masing target tersebut?
- Tingkat ketersediaan dan privasi apa yang berlaku untuk artikel, rekomendasi, komentar, dan personalisasi?
- Apakah halaman di-cache di CDN, dan varian pengguna, wilayah, atau eksperimen apa saja yang ada?
- Pada kegagalan modul yang lambat, apakah UI harus menampilkan status kosong, data usang, atau mencoba ulang?
- Jalur utama mana yang harus tetap berfungsi jika JavaScript klien gagal?
Jawaban 30 detik
“Kirimkan shell yang tidak bergantung pada data yang lambat, lalu bagi rekomendasi, komentar, dan personalisasi ke dalam batasan Suspense dengan anggaran waktu yang eksplisit. Setiap batasan memiliki timeout server, error yang dapat diobservasi, dan fallback yang dapat diterima, sehingga kegagalan tetap terisolasi secara lokal. Klien menangani percobaan ulang terbatas dan interaksi setelah hidrasi. Cache hanya fragmen publik yang aman, serta pantau TTFB, LCP, INP, error, dan latensi batasan.”
Pembahasan mendalam langkah demi langkah
Langkah 1: Pisahkan shell dan batasan
Selesaikan perutean, judul, struktur artikel, dan semantik utama secara sinkron. Tempatkan rekomendasi, komentar, dan personalisasi dalam batasan terpisah. Sebuah batasan harus mewakili area yang dapat dipahami pengguna, bukan sekadar kumpulan sembarang dari dependensi jarak jauh.
shell: navigation + heading + article outline
boundary A: recommendations, budget 300 ms
boundary B: comments, budget 500 ms
boundary C: personalized actions, private and uncachedPertahankan heading, dimensi, dan semantik di setiap fallback untuk menghindari pergeseran tata letak (layout shift). Jangan memecah halaman terlalu jauh sehingga pengguna tidak dapat memahami apa yang sedang dimuat.
Langkah 2: Bangun streaming dan pembatalan
Gunakan API rendering server streaming dari framework sehingga shell masuk ke dalam respons terlebih dahulu dan batasan mengikuti saat data selesai diproses. Lampirkan batas waktu permintaan; setelah timeout, batalkan panggilan jarak jauh dan keluarkan fallback yang dapat diterima. Klien tidak boleh menunggu tugas server yang telah dibatalkan.
Catat peristiwa mulai, selesai, timeout, dan error pada batasan. Ketika klien terputus, batalkan pengambilan data yang belum selesai sehingga halaman yang ditinggalkan tidak menghabiskan kapasitas database atau rekomendasi.
Langkah 3: Tangani error server dan klien
Error di dalam batasan server harus diselesaikan ke fallback batasan tersebut sambil tetap mempertahankan shell dan elemen selevel yang telah selesai. Lampirkan pengidentifikasi batasan yang stabil dan ID pelacakan permintaan untuk operator, sementara teks yang ditampilkan kepada pengguna hanya menyatakan bahwa bagian tersebut tidak tersedia untuk sementara waktu.
Setelah kode klien dimuat, izinkan percobaan ulang terbatas berbasis backoff untuk batasan yang memenuhi syarat. Percobaan ulang memerlukan batas percobaan, kondisi idempoten, dan pembatalan. Jika skrip klien gagal, teks artikel, tautan, dan formulir utama harus tetap dapat digunakan.
Langkah 4: Tentukan batasan cache
Cache konten artikel publik dan modul non-pengguna dengan kunci untuk rute, bahasa, wilayah, dan versi konten. Batasan yang dipersonalisasi tidak boleh masuk ke dalam cache HTML publik; eksperimen harus eksplisit dalam kunci atau diisolasi di edge.
Cache hit tidak boleh menyembunyikan data sumber yang usang. Catat waktu pembuatan, masa kedaluwarsa, dan versi untuk setiap fragmen, serta gunakan kebijakan kesegaran yang konsisten. Berhati-hatilah dalam menyimpan cache aliran akhir yang digabungkan; fragmen yang aman biasanya merupakan batasan yang lebih baik.
Langkah 5: Pertahankan aksesibilitas dan stabilitas tata letak
Pertahankan heading semantik, landmark, dan batasan dimensi yang sama pada fallback dan konten akhir. Penggantian tidak boleh memindahkan fokus keyboard ke node yang tidak terlihat. Wilayah dinamis memerlukan pengumuman status yang tepat tanpa membaca ulang seluruh halaman secara berulang-ulang.
Cadangkan dimensi gambar dan media serta jaga kestabilan geometri skeleton; pantau CLS. Simpan konten utama artikel di dalam batasan awal yang terlihat, dan jangan meletakkan elemen LCP di belakang permintaan long-tail yang tidak terkontrol.
Langkah 6: Tambahkan gerbang rilis dan observabilitas
Pengujian pra-rilis mencakup dependensi yang lambat, respons 500, pemutusan koneksi, kegagalan skrip klien, polusi cache, dan pembatalan. Di lingkungan produksi, ukur TTFB, LCP, INP, p50/p95 batasan, tingkat timeout, tingkat fallback, dan keberhasilan percobaan ulang berdasarkan rute, batasan, dan dependensi.
Selama uji coba canary, amati shell dan batasan penting sebelum membuka personalisasi berisiko tinggi. Jika error atau latensi batas (tail latency) melewati ambang batas, kembalikan komposisi batasan atau fallback statis alih-alih memperluas lalu lintas pengguna.
Contoh jawaban yang kuat
Saya akan menentukan anggaran layar pertama dan tingkat ketersediaan, lalu memisahkan shell artikel, rekomendasi, komentar, dan personalisasi ke dalam batasan Suspense yang independen. Setiap batasan mendapatkan timeout, fallback, jalur pembatalan, dan ID pelacakan; kegagalan tetap bersifat lokal. Fragmen publik menggunakan dimensi cache yang aman, sementara personalisasi tidak pernah masuk ke cache bersama. Saya akan menguji pemutusan koneksi dan kegagalan skrip, serta memantau LCP, INP, CLS, p95 batasan, dan tingkat fallback.
Kesalahan umum
- Membungkus seluruh halaman dalam satu batasan → dependensi paling lambat memblokir semuanya → pisahkan berdasarkan area yang dapat dipahami pengguna.
- Tidak memberikan dimensi tetap pada fallback → penggantian menyebabkan CLS → cadangkan ruang dan pertahankan semantik.
- Menaruh HTML yang dipersonalisasi di cache publik → data pengguna dapat bocor → isolasi fragmen privat dan sertakan dimensi kunci yang aman.
- Mencoba ulang tanpa henti setelah timeout server → beban dependensi diamplifikasi → gunakan anggaran, backoff, batasan, dan pembatalan.
- Hanya menguji keberhasilan → pemutusan koneksi atau kegagalan skrip membuat halaman tidak dapat digunakan → uji error, pembatalan, dan degradasi tanpa skrip.
Pertanyaan lanjutan dan tanggapan
Pertanyaan lanjutan 1: Apakah memiliki lebih banyak batasan selalu lebih baik?
Tidak. Batasan harus dipetakan ke area pengguna dan domain kegagalan yang independen. Batasan yang terlalu detail menambah gangguan fallback, biaya pemantauan, dan varian cache; batasan yang terlalu kasar memperbesar domain pemblokiran.
Pertanyaan lanjutan 2: Bagaimana cara mencegah satu error menghentikan streaming?
Pertahankan pemulihan di dalam jalur server dan klien batasan tersebut, pertahankan shell yang sudah dikirim, dan sediakan fallback yang stabil untuk setiap batasan. Uji kegagalan setelah sebagian respons telah dikirim.
Pertanyaan lanjutan 3: Metrik apa yang membuktikan bahwa desain tersebut berhasil?
Lacak TTFB, LCP, INP, CLS, p95 batasan, tingkat timeout, tingkat fallback, dan keberhasilan percobaan ulang secara bersamaan. Waktu respons rata-rata saja menyembunyikan tail latency dan kegagalan lokal.
Pertanyaan lanjutan 4: Bagaimana Anda mencegah kebocoran cache pada data eksperimen atau pengguna?
Sertakan dimensi keamanan pengguna, eksperimen, wilayah, bahasa, dan versi konten dalam kunci. Fragmen yang keamanannya tidak dapat dibuktikan harus dijauhkan dari cache publik, dan pengujian replay lintas-pengguna memverifikasi isolasi tersebut.