Berurusan dengan cache browser di aplikasi satu halaman

27

Saya mencoba mencari cara menangani cache browser web dengan benar untuk aplikasi satu halaman.

Saya memiliki desain yang cukup khas: beberapa file HTML, JS dan CSS mengimplementasikan SPA, dan banyak data JSON yang dikonsumsi oleh SPA. Masalah muncul ketika saya ingin mendorong pembaruan: Saya memperbarui bagian statis situs dan kode yang menghasilkan JSON pada saat yang sama, tetapi browser klien sering memiliki bagian statis di-cache, jadi kode lama mencoba memproses data baru dan mungkin (tergantung pada perubahan yang dibuat) mengalami masalah. (Secara khusus, IE tampaknya lebih agresif daripada Chrome atau Firefox tentang menggunakan JS yang di-cache tanpa memvalidasi ulang.)

Apa cara terbaik untuk menangani ini?

  1. Pastikan perubahan JSON saya kompatibel dengan mundur, dan menganggap cache browser akan kedaluwarsa dalam jangka waktu yang masuk akal.
  2. Sematkan nomor versi di JS statis dan JSON, kemudian jalankan window.location.reload(true);jika tidak cocok.
  3. Cari tahu kombinasi header yang sesuai ( must-revalidateatau no-cacheatau apa pun; sumber berbeda-beda tentang cara melakukan ini) untuk memastikan bahwa browser selalu memvalidasi ulang semua sumber daya pada setiap beban, bahkan jika itu berarti beberapa perjalanan bolak-balik tambahan untuk memuat situs.
  4. Kelola kontrol-cache saya dan kedaluwarsa tajuk sehingga konten statis kedaluwarsa saat saya ingin mendorong pembaruan.
  5. Sesuatu yang lain
Josh Kelley
sumber
1
Telah mendengar # 3 dan # 4 tiba-tiba gagal di kontrol browser web tertanam jika lingkungan Anda jahat ( batuk iOS) dari rekan kerja. # 1 dan # 2 bisa menjadi pilihan tingkat aplikasi tetapi masih (?) Dapat menyebabkan masalah cache untuk sumber daya lain atau untuk memuat sebagian sumber daya. Satu-satunya hal yang saya lihat andal bekerja dalam kode siap produksi adalah mengambil yoururl.html? <SomeTimeStamp> karena ini akan memalsukan sebagian besar mekanisme caching. Bonus: gulung seluruh aplikasi web Anda ke dalam file sehingga memuat baik secara atom berhasil atau gagal. Kelemahan: berfungsi terbaik pada tautan lokal. Jarak tempuh Anda mungkin beragam. Semoga berhasil!
J Trana
2
+1 untuk menggunakan nomor versi atau stempel waktu sebagai parameter URL untuk sumber daya.
9000

Jawaban:

14

Anda membutuhkan solusi penghilang cache . Peran penghilang cache adalah:

  1. Ganti nama sumber daya menjadi nama unik tergantung pada kontennya.
  2. Perbarui semua referensi ke sumber daya tersebut.

Dalam proyek berbasis Grunt, sudah biasa menggunakan grunt-rev untuk memastikan bahwa semua file yang perlu di-refresh diberi nama unik, berdasarkan kontennya.

Jika Anda memastikan bahwa file JSON Anda mendapatkan nama file cachebusting bersama dengan referensi mereka di Javascript Anda, klien akan selalu memuat file JSON yang diharapkan Javascript.

Keuntungan dari penamaan file berbasis hash adalah bahwa file yang tidak berubah akan mendapatkan nama file yang sama setelah cache-busting, sehingga browser dapat terus menggunakan konten yang di-cache dengan aman ketika tidak diubah.

Jelas ini adalah jenis hal yang Anda ingin otomatis sebagai bagian dari produksi produksi proyek Anda sehingga Anda tidak perlu melacak perubahan nama file & referensi secara manual.

Ted Percival
sumber
2
+1 untuk bit "penghilang cache" yang dicetak miring, yang membuka pintu untuk benar-benar Google melakukan hal ini secara produktif.
Zak Kus
@Ted Percival - framework yeoman melakukan ini, yang saya gunakan, tetapi saya melihat masalah. ketika saya merilis build baru, browser mungkin memiliki index.html di-cache dengan referensi ke file-file lama ... dan browser mendapatkan kesalahan. bagaimana saya memperbaikinya? (A.) symlink semua nama file lama ke yang baru (ini berfungsi) (B.) tambahkan header no-cache ke index.html (tetapi apakah ini selalu dihormati) (C.) tambahkan .htaccess untuk mengenali file yang telah dibatalkan. dan cari basisnya (mis. 12345.main.js -> main.js)
timh
5

Anda dapat menggunakan if-modified-since + last-modifiedatau if-none-match + etagtajuk bersama dengan cache-controltajuk yang tepat . (Mungkin ada bug browser , tetapi tidak ada yang tidak dapat Anda kelola di browser terbaru.)

Jika file-file itu statis, maka saya sarankan Anda untuk menggunakan if-modified-since, karena itu dapat dilakukan secara otomatis dengan server HTTP yang dikonfigurasi dengan baik. Seharusnya mengirim 304 kembali jika file tidak diubah sejak unduhan terakhir.

Saya tidak berpikir Anda # 1 dan # 2 akan bekerja dalam jangka panjang. # 3 atau # 4 dapat bekerja. # 3 lebih sederhana, tetapi Anda harus belajar cara mengatasi masalah ini hanya sekali. Jadi saya akan mencoba # 4 jika saya jadi Anda, tetapi solusinya mungkin tergantung pada browser apa yang digunakan pelanggan Anda ... Misalnya IE8 memiliki masalah dengan memperbarui cache ajax, dll ...

inf3rno
sumber
2

Jika Anda dapat memasukkan Java Servlet Filter di SPA Anda, berikut ini adalah solusi yang berfungsi: CorrectBrowserCacheHandlerFilter.java

Pada dasarnya, ketika browser Anda meminta file statis, server akan mengarahkan ulang setiap permintaan ke yang sama tetapi dengan parameter permintaan hash ( ?v=azErTmisalnya) yang tergantung pada konten file statis target.

Melakukan hal ini, browser tidak akan pernah men-cache file statis yang dideklarasikan dalam Anda index.htmlmisalnya (karena akan selalu menerima a 302 Moved Temporarily), tetapi hanya akan melakukan cache yang dengan versi hash (server akan menjawabnya 200). Jadi cache browser akan digunakan secara efisien untuk file-file statis dengan versi hash.

Penafian: Saya penulis CorrectBrowserCacheHandlerFilter.java.

Anthony O.
sumber