Perusakan cache melalui params

123

Kami ingin menyimpan kerusakan pada penerapan produksi, tetapi tidak membuang banyak waktu untuk mencari tahu sistem untuk melakukannya. Pikiran saya adalah menerapkan param di akhir file css dan js dengan nomor versi saat ini:

<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>

Dua pertanyaan: Apakah ini akan merusak cache secara efektif? Akankah param menyebabkan browser tidak pernah menyimpan respons dari url itu karena param menunjukkan bahwa ini adalah konten dinamis?

Brad Herman
sumber

Jawaban:

115

Parameter ?v=1.123menunjukkan string kueri, dan browser akan menganggapnya sebagai jalur baru dari, katakanlah ?v=1.0,. Sehingga menyebabkannya memuat dari file, bukan dari cache. Terserah kamu.

Dan, browser akan menganggap bahwa sumber akan tetap sama saat Anda menelepon lagi ?v=1.123dan harus menyimpannya dalam cache dengan string itu. Jadi itu akan tetap di-cache, bagaimanapun server Anda diatur, sampai Anda pindah ke ?v=1.124atau seterusnya.

Marshall
sumber
4
Mengutip Steve Souders: "Untuk mendapatkan manfaat dari caching oleh proxy populer, hindari revving dengan querystring dan sebaliknya rev nama filenya sendiri." Penjelasan lengkap dapat ditemukan di sini: stevesouders.com/blog/2008/08/23/…
lao
25
Posting blog itu mendekati satu dekade sekarang. Apakah menurut Anda penyedia cache dan CDN belum menampungnya? Squid sepertinya bisa menyimpan dokumen dengan query string sekarang .
jeteon
1
Mungkin ini membantu seseorang: Secara pribadi, saya menggunakan stempel waktu modifikasi file sebagai parameter versi 'otomatis', mis. <link rel="stylesheet" href="style.css?v=1487935578" />
oelna
Saya pribadi tidak mengerti mengapa, tetapi Lara Hogan (Swanson) (manajer teknik di Etsy) tidak merekomendasikan penggunaan parameter kueri untuk perusakan cache. Saya pikir ini ada hubungannya dengan proxy cache antara pengguna dan server.
Sam Rueby
36

Dua pertanyaan: Apakah ini akan merusak cache secara efektif?

Iya. Bahkan Stack Overflow menggunakan metode ini, meskipun saya ingat bahwa mereka (dengan jutaan pengunjung mereka per hari dan miliaran versi dan konfigurasi klien dan proxy yang berbeda) memiliki beberapa kasus tepi yang aneh bahkan ini tidak cukup untuk memecahkan cache. Tetapi asumsi umumnya adalah bahwa ini akan berhasil, dan merupakan metode yang cocok untuk menghentikan caching pada klien.

Akankah param menyebabkan browser tidak pernah menyimpan respons dari url itu karena param menunjukkan bahwa ini adalah konten dinamis?

Tidak. Parameter tidak akan mengubah kebijakan caching; header caching yang dikirim oleh server masih berlaku, dan jika tidak terkirim, browser default.

Pekka
sumber
1
@spender Saya tidak dapat menemukan referensi sekarang. Sayangnya, ada artikel blog yang panjang atau jawaban SO di mana Jeff Atwood membicarakannya (IIRC)
Pekka
2
@spender Saya telah membaca bahwa beberapa server proxy (baik yang lama, atau dapat dikonfigurasi untuk) mengabaikan string kueri saat melakukan cache.
MrWhite
2
@ Pengirim - Saya pernah mendengar hal yang sama, dan menurut saya mengubah nama file, atau jalur adalah opsi terbaik. Mungkin paling mudah untuk hanya membiarkan memindahkan semua file statis Anda di bawah nama folder berversi, misalnya /static/v22/file.css, karena Anda dapat melakukan banyak file dengan mengganti nama folder tunggal, misalnya /static/v23/file.cssdan/static/v23/mystuff.js
Brad Parks
22

Lebih aman untuk memasukkan nomor versi pada nama file yang sebenarnya. Hal ini memungkinkan beberapa versi ada sekaligus sehingga Anda dapat meluncurkan versi baru dan jika halaman HTML yang di-cache masih ada yang meminta versi lama, mereka akan mendapatkan versi yang sesuai dengan HTML-nya.

Perhatikan, dalam salah satu penerapan berversi terbesar di mana pun di internet, jQuery menggunakan nomor versi dalam nama file yang sebenarnya dan dengan aman memungkinkan beberapa versi untuk hidup berdampingan tanpa logika sisi server khusus (setiap versi hanyalah file yang berbeda).

Ini merusak cache sekali ketika Anda menyebarkan halaman baru dan file baru yang ditautkan (yang Anda inginkan) dan sejak saat itu versi tersebut dapat di-cache secara efektif (yang juga Anda inginkan).

jfriend00
sumber
Saya setuju dengan itu, tetapi jauh lebih mudah untuk hanya menambahkan Sinatra? V = <% = VERSION%> ke semua permintaan css dan js dibandingkan harus mengontrol setiap file satu per satu. Akhirnya kita akan beralih ke sinatra-assetpack, yang akan memproses dan memampatkan semua file dan benar-benar menambahkan versi # ke nama file, yang kemudian akan membuat kita lebih mudah mengontrolnya satu per satu.
Brad Herman
1
Saya setuju memasukkan nomor versi dalam nama file adalah solusi paling aman jika Anda ingin memastikan 10.000%, tetapi saya tidak mengikuti argumen "beberapa versi ada sekaligus". URL dengan parameter kueri berbeda dari URL yang sama dengan parameter kueri yang berbeda. Mereka harus diperlakukan sebagai dua sumber yang berbeda oleh klien; jika tidak, klien rusak.
Pekka
2
@Pekka - hal nomor versi dapat memungkinkan beberapa versi ada sekaligus, tetapi itu membutuhkan kerja sama server untuk memetakan parameter kueri ke file aktual yang benar. Saya tidak berpikir itulah yang dilakukan OP di sini dan ada sedikit alasan untuk meminta kerumitan saat memodifikasi nama file jauh lebih sederhana dan tidak memerlukan kerja sama server. Jelas keduanya bisa bekerja.
jfriend00
11

Seperti yang dikatakan orang lain, perusakan cache dengan parameter kueri biasanya dianggap sebagai Ide Buruk (tm), dan sudah lama sekali. Lebih baik mencerminkan versi dalam nama file. Boilerplate Html5 merekomendasikan penggunaan string kueri, antara lain.

Meskipun demikian, dari rekomendasi yang saya lihat yang mengutip sebuah sumber, semuanya tampaknya mengambil kebijaksanaan mereka dari artikel tahun 2008 oleh Steve Souders. Kesimpulannya didasarkan pada perilaku proxy pada saat itu, dan mungkin relevan atau tidak saat ini. Namun, jika tidak ada informasi terkini, mengubah nama file adalah opsi yang aman.

hashchange
sumber
9

Ini akan merusak cache sekali, setelah klien mengunduh sumber daya, setiap respons lain akan disajikan dari cache klien kecuali:

  1. parameter v diperbarui.
  2. klien membersihkan cache mereka
ncremins.dll
sumber
6

Secara umum ini seharusnya baik-baik saja, tetapi mungkin ini tidak berfungsi jika ada cache perantara (proxy) yang dikonfigurasi untuk mengabaikan parameter permintaan.

Misalnya, jika Anda menyajikan konten statis melalui Akamai CDN, ini dapat dikonfigurasi untuk mengabaikan parameter permintaan guna mencegah perusakan cache menggunakan metode ini.

Ken Liu
sumber
5

Ini sangat bergantung pada seberapa kuat Anda menginginkan caching Anda. Misalnya, server proxy squid (dan mungkin yang lain) secara default tidak menyimpan URL yang disajikan dengan querystring - setidaknya, itu terjadi ketika artikel itu ditulis. Jika Anda tidak keberatan dengan kasus penggunaan tertentu yang menyebabkan kehilangan cache yang tidak perlu, lanjutkan dengan parameter kueri. Tetapi sangat mudah untuk mengatur skema perusak cache berbasis nama file yang menghindari masalah ini.

Bobby Jack
sumber
5
Proxy squid yang dikutip dalam artikel Steve Souders telah mengubah kebijakan cache default mereka. Sejak versi 2.7 (Mei 2008) dan versi 3.1 (Maret 2010), perilaku default adalah menyimpan konten dinamis ke cache.
Josh Rack
5

Temukan perbandingan 2 teknik (string kueri vs nama file) di sini :

Versi sebagai string kueri memiliki dua masalah.

Pertama, mungkin tidak selalu browser yang mengimplementasikan caching yang perlu kita hancurkan. Dikatakan bahwa beberapa proxy (mungkin lebih lama) mengabaikan querystring sehubungan dengan perilaku caching mereka.

Kedua, dalam skenario penerapan tertentu yang lebih kompleks, di mana Anda memiliki beberapa server frontend dan / atau beberapa server backend, pemutakhiran sama sekali tidak instan. Anda harus dapat menyajikan aset versi lama dan baru secara bersamaan. Lihat misalnya bagaimana hal ini memengaruhi Anda saat menggunakan Google App Engine.

pengguna
sumber
4

Pendekatan serupa lainnya adalah menggunakan htaccess mod_rewrite untuk mengabaikan bagian jalur saat menyajikan file. Halaman indeks Anda yang tidak pernah di-cache mereferensikan jalur terbaru ke file.

Dari perspektif pengembangan, semudah menggunakan params untuk nomor versi, tetapi sekuat pendekatan nama file.

Gunakan bagian jalur yang diabaikan untuk nomor versi, dan server mengabaikannya dan menyajikan file yang tidak di-cache.

1.2.3/css/styles.cssmenyajikan file yang sama seperti css/styles.csssejak direktori pertama dihapus dan diabaikan oleh file htaccess

Termasuk file berversi

<?php
  $version = "1.2.3";
?>

<html>
  <head>
    <meta http-equiv="cache-control" content="max-age=0" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="0" />
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    <meta http-equiv="pragma" content="no-cache" />
    <link rel="stylesheet" type="text/css" href="<?php echo $version ?>/css/styles.css">
  </head>
  <body>
    <script src="<?php echo $version ?>/js/main.js"></script>
  </body>
</html>

Perhatikan bahwa pendekatan ini berarti Anda perlu menonaktifkan cache halaman indeks Anda - Menggunakan tag <meta> untuk menonaktifkan cache di semua browser?

file .htaccess

RewriteEngine On

# if you're requesting a file that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-f 
# likewise if a directory that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-d 

# otherwise, rewrite foo/bar/baz to bar/baz - ignore the first directory
RewriteRule ^[^/]+/(.+)$ $1 [L] 

Anda dapat mengambil pendekatan yang sama pada platform server apa pun yang memungkinkan penulisan ulang url

(rewrite condition diadaptasi dari mod_rewrite - rewrite directory ke query string kecuali / #! / )

... dan jika Anda memerlukan perusakan cache untuk halaman indeks / titik masuk situs, Anda selalu dapat menggunakan JavaSript untuk menyegarkannya.

alexanderbird.dll
sumber
2
<script type="text/javascript">
// front end cache bust

var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];   
for (i=0; i < cacheBust.length; i++){
     var el = document.createElement('script');
     el.src = cacheBust[i]+"?v=" + Math.random();
     document.getElementsByTagName('head')[0].appendChild(el);
}
</script> 
Conete Cristian
sumber
Selama pengembangan / pengujian rilis baru, cache dapat menjadi masalah karena browser, server, dan bahkan terkadang telco 3G (jika Anda melakukan penerapan seluler) akan menyimpan cache konten statis (misalnya JS, CSS, HTML, img). Anda dapat mengatasinya dengan menambahkan nomor versi, nomor acak atau cap waktu ke URL misalnya: JSP: <script src = "js / excel.js? Time = <% = new java.util.Date ()%>"> </ script> Jika Anda menjalankan HTML murni (bukan halaman server JSP, ASP, PHP) server tidak akan membantu Anda. Di browser, tautan dimuat sebelum JS berjalan, oleh karena itu Anda harus menghapus tautan dan memuatnya dengan JS
Conete Cristian
Saya tidak berpikir ini akan memuat file JS secara berurutan.
Stealth Rabbi
0
 <script>
    var storedSrcElements = [
         "js/exampleFile.js",
         "js/sampleFile.js",
         "css/style.css"
          ];

    var head= document.getElementsByTagName('head')[0];
    var script;
    var link;
    var versionNumberNew = 4.6;

    for(i=0;i<storedSrcElements.length;i++){
     script= document.createElement('script');
     script.type= 'text/javascript';
     script.src= storedSrcElements[i] + "?" + versionNumberNew;
     head.appendChild(script);
    }     


     </script> 


       ### Change the version number  (versionNumberNew) when you want the new files to be loaded  ###
Teja
sumber
0

Semoga ini bisa membantu Anda untuk menyuntikkan file JS eksternal

<script type="text/javascript"> 
var cachebuster = Math.round(new Date().getTime() / 1000); 
document.write('<scr'+'ipt type="text/javascript" src="external.js?cb=' +cachebuster+'"></scr' + 'ipt>');
</script>

Sumber - Kode Cachebuster di JavaScript

Vinit Kadkol
sumber