Bagaimana saya bisa memaksa klien untuk me-refresh file JavaScript?


595

Kami saat ini bekerja dalam versi beta pribadi dan masih dalam proses membuat perubahan yang cukup cepat, meskipun jelas saat penggunaan mulai meningkat, kami akan memperlambat proses ini. Yang sedang berkata, satu masalah yang kita hadapi adalah bahwa setelah kita mendorong pembaruan dengan file JavaScript baru, browser klien masih menggunakan versi cache file dan mereka tidak melihat pembaruan. Jelas, pada panggilan dukungan, kami hanya dapat memberi tahu mereka untuk melakukan ctrlF5penyegaran untuk memastikan bahwa mereka mendapatkan file terbaru dari server, tetapi akan lebih baik untuk menangani ini sebelum waktu itu.

Pemikiran kami saat ini adalah dengan cukup melampirkan nomor versi ke nama file JavaScript dan kemudian ketika perubahan dibuat, tambahkan versi pada skrip dan perbarui semua referensi. Ini pasti menyelesaikan pekerjaan, tetapi memperbarui referensi pada setiap rilis bisa menjadi rumit.

Karena saya yakin kami bukan yang pertama menangani ini, saya pikir saya akan membuangnya ke komunitas. Bagaimana Anda memastikan klien memperbarui cache mereka ketika Anda memperbarui kode Anda? Jika Anda menggunakan metode yang dijelaskan di atas, apakah Anda menggunakan proses yang menyederhanakan perubahan?


Jawaban:


529

Sejauh yang saya tahu solusi umum adalah menambahkan ?<version>tautan src skrip.

Contohnya:

<script type="text/javascript" src="myfile.js?1500"></script>

Saya berasumsi pada titik ini bahwa tidak ada cara yang lebih baik daripada mencari-ganti untuk menambah "nomor versi" ini di semua tag skrip?

Anda mungkin memiliki sistem kontrol versi yang melakukannya untuk Anda? Sebagai contoh, sebagian besar sistem kontrol versi memiliki cara untuk secara otomatis menyuntikkan nomor revisi pada saat check-in.

Akan terlihat seperti ini:

<script type="text/javascript" src="myfile.js?$$REVISION$$"></script>

Tentu saja, selalu ada solusi yang lebih baik seperti ini .


5
Adakah yang tahu kalau IE7 mengabaikan ini? Tampaknya mengabaikan data yang ditambahkan dan menggunakan file cache ketika saya menguji dalam tampilan komparabilitas IE8.
Shane Reustle

4
Saya selalu tahu string kueri adalah pasangan nilai kunci seperti pada? Ver = 123. Terima kasih! :)
Ankur-m

6
Saya pikir ini bukan tentang nomor versi yang lebih tinggi atau lebih rendah tetapi tentang mengubah nilai variabel yang ditambahkan ke sesuatu browser belum bisa di-cache.
Max Girkens

2
Kami baru-baru ini mengalami masalah yang sama, dan yang terbaik yang dapat saya temukan adalah fungsi sederhana yang dilampirkan "? Mod = 123456" di mana 123456 adalah cap waktu unix dari tanggal yang dimodifikasi pada file. Itu tampaknya untuk memperbaiki masalah sambil tetap memungkinkan untuk caching yang sesuai. Namun, saya masih melihat browser mengabaikan aba-aba arahan ini dan tetap menggunakan JS lama, tetapi saya tidak tahu bahwa ada "perbaikan penuh" yang elegan.
VPel

31
Untuk kesadaran: ini dianggap sebagai peretasan. Metode ini menipu browser untuk berpikir bahwa file baru sedang ditentukan, karena hanya melihat nama file lengkap tanpa menafsirkannya. foo.js?1bukan nama yang sama dengan foo.js?2, jadi browser akan berpikir mereka adalah dua file yang berbeda. Satu kelemahan adalah bahwa kedua file secara bersamaan akan ada di cache pengguna, mengambil ruang yang tidak perlu.
Lee White

88

Menambahkan waktu saat ini ke URL memang merupakan solusi umum. Namun, Anda juga dapat mengelola ini di tingkat server web, jika mau. Server dapat dikonfigurasi untuk mengirim header HTTP berbeda untuk file javascript.

Misalnya, untuk memaksa file di-cache tidak lebih dari 1 hari, Anda akan mengirim:

Cache-Control: max-age=86400, must-revalidate

Untuk beta, jika Anda ingin memaksa pengguna untuk selalu mendapatkan yang terbaru, Anda akan menggunakan:

Cache-Control: no-cache, must-revalidate

3
bisakah Anda lebih spesifik?
Kreker

6
Dia berbicara tentang header yang dikirim oleh server web untuk setiap file. Seharusnya dapat dikonfigurasi di Apache misalnya. Saya pikir ini akan menjadi pendekatan terbaik
Pierre de LESPINAY

1
di mana Anda mengkonfigurasi ini?
Diego

2
Untuk pengembangan webapp, itu mungkin solusi yang bagus. Untuk situs produksi, di mana Anda tidak ingin membatalkan cache selamanya, itu bukan solusi yang baik kecuali jika Anda tahu bahwa masing-masing dan setiap browser klien target telah datang ke situs. Itu membuat saya berpikir tentang fitur server web potensial: menyesuaikan parameter usia maks sesuai dengan tanggal penyebaran yang dikonfigurasi. Itu akan luar biasa.
Claude Brisson

Chrome MEMBUTUHKAN pengaturan ini untuk melakukan cache dengan benar. Tanpa mereka, Chrome akan menyimpan file selamanya. Mozilla menggunakan standar yang jauh lebih masuk akal. Lihat lebih lanjut di: agiletribe.wordpress.com/2018/01/29/caching-for-chrome
AgilePro

42

Google Page-Speed: Jangan sertakan string kueri dalam URL untuk sumber daya statis. Kebanyakan proksi, terutama Squid hingga versi 3.0, tidak menyimpan sumber daya dengan "?" dalam URL mereka bahkan jika kontrol-Cache: header publik hadir dalam respons. Untuk mengaktifkan cache proxy untuk sumber daya ini, hapus string kueri dari referensi ke sumber daya statis, dan alih-alih enkode parameter ke dalam nama file itu sendiri.

Dalam hal ini, Anda dapat memasukkan versi ke URL misalnya: http://abc.com/ v1.2 /script.js dan menggunakan apache mod_rewrite untuk mengarahkan ulang tautan ke http://abc.com/script.js . Ketika Anda mengubah versi, browser klien akan memperbarui file baru.


Saya sudah mencoba? solusi dan di IE8 dan saya mendapatkan kesalahan javascript. Mod rewrite adalah pilihan tetapi dalam banyak kasus kami tidak akan memiliki banyak kontrol atas server. Saya lebih suka menambahkan versi dalam file js sendiri atau memiliki folder untuk setiap versi
Karthik Sankar

@ Hắc Huyền Minh: Tetapi ketika skrip akan dimuat ulang, itu tidak boleh dimuat ulang dari proxy-cache ...
Stefan Steiger

34

Penggunaan ini telah dirusak: https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache

Jawaban ini hanya terlambat 6 tahun, tetapi saya tidak melihat jawaban ini di banyak tempat ... HTML5 telah memperkenalkan Cache Aplikasi yang digunakan untuk menyelesaikan masalah ini. Saya menemukan bahwa kode server baru yang saya tulis sedang menabrak javascript lama yang disimpan di browser orang, jadi saya ingin mencari cara untuk mengakhiri javascript mereka. Gunakan file manifes yang terlihat seperti ini:

CACHE MANIFEST
# Aug 14, 2014
/mycode.js

NETWORK:
*

dan hasilkan file ini dengan cap waktu baru setiap kali Anda ingin pengguna memperbarui cache mereka. Sebagai catatan tambahan, jika Anda menambahkan ini, browser tidak akan memuat ulang (bahkan ketika pengguna me-refresh halaman) sampai manifes memberitahukannya.


Solusi ini sangat bagus, selama Anda ingat untuk memperbarui file manifes :)
Mattis

24
Silakan baca dokumentasi karena fitur ini telah dihapus dari pengembang
Web.mozilla.org/en-US/docs/Web/HTML/…

1
FWIW, saya akhirnya tidak menggunakan solusi ini. Jauh lebih mudah menggunakan / mempertahankan ?<version> pendekatan itu.
amos

28

Bagaimana kalau menambahkan filesize sebagai parameter load?

<script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script>

Jadi, setiap kali Anda memperbarui file, parameter "filever" berubah.

Bagaimana ketika Anda memperbarui file dan hasil pembaruan Anda dalam ukuran file yang sama? apa peluangnya?


4
Ini menggunakan tag PHP dan jika seseorang menggunakan PHP, itu memang ide yang bagus.
Jerther

1
Saya pikir menambahkan yang diubah akan lebih baik daripada filesize :)
Mazz

2
Pikiran awal saya adalah menambahkan hash file, bukan versi.
Mike Cheel

Saya menganggap itu juga berfungsi jika menambahkan cap waktu Unix, kan? mis. '... file.js? filever = <? = time ()?>
garanda

3
gunakan filemtime ($ file) itu output timestamp file, dengan waktu () Anda tidak dapat menggunakan cache karena itu berubah setiap detik.
neoteknic

19

Tidak semua file cache cache dengan '?' di dalamnya. Apa yang saya lakukan untuk memastikan itu di-cache sebanyak mungkin, saya memasukkan versi dalam nama file.

Jadi alih-alih stuff.js?123, saya yang melakukannyastuff_123.js

Saya menggunakan mod_redirect(saya pikir) di apache have stuff_*.jsuntuk pergistuff.js


Bisakah Anda jelaskan apa yang Anda lakukan di .htaccess dengan mod_redirect?
Venkat D.

3
Penjelasan terperinci tentang metode ini dapat ditemukan di particletree.com/notebook/…
Karl Bartel

3
Akan lebih bagus jika Anda bisa memasukkan .htaccesskode Anda dalam jawaban Anda untuk referensi di masa mendatang.
Fizzix

1
Browser mana yang tidak menembolok file dengan "?" di dalamnya?
rosell.dk

13

Untuk halaman ASP.NET saya menggunakan yang berikut ini

SEBELUM

<script src="/Scripts/pages/common.js" type="text/javascript"></script>

SETELAH (paksa ulang)

<script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>

Menambahkan DateTime.Now.Ticks bekerja dengan sangat baik.


31
Yang ini bertentangan dengan semua mekanisme caching di sisi klien. parameter dummy harus diganti dengan sesuatu seperti "{versi mayor} _ {minor_version} _ {build_number} _ {Revisi} yang akan menjadi unik untuk setiap rilis.
Tohid

14
Walaupun ini mungkin solusi dewa dalam lingkungan pengembangan, ini tidak cocok untuk produksi. Ini sepenuhnya akan menonaktifkan cache setiap kali halaman dimuat untuk file. Bayangkan 10k beban halaman per hari dengan satu file 50Kb, itu mewakili 500Mb file Javascript setiap hari.
PhilDulac

@ PhilDulac, Anda dapat mengubahnya dari Kutu untuk mengembalikan nilai string hari misalnya, atau bulan, atau minggu dalam sebulan. Pada akhirnya ini hanya menunjukkan kepada Anda bagaimana menggunakan pendekatan? V
alex

3
@alex Memang. Saya hanya ingin memperingatkan bahwa jika penggunaan yang ditunjukkan dalam jawaban membuat jalan untuk produksi, itu dapat memiliki dampak yang tidak muncul dalam pengembangan.
PhilDulac

2
Cara yang mungkin untuk memastikan bahwa salinan baru dapat dimuat sekali setiap hari mungkin dengan menggunakan tipe '<script src = "/ Scripts / pages / common.js? Ver <% = DateTime.Now.ToString (" yyyyMMdd ")%>" = "teks / javascript"> </script> '. Jadi dimuat sekali di awal hari, lalu di-cache.
Robb Sadler

7

Untuk ASP.NET saya kira solusi berikutnya dengan opsi lanjutan (mode debug / rilis, versi):

File Js atau Css disertakan dengan cara seperti ini:

<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />

Global.JsPostfix dan Global.CssPostfix dihitung dengan cara berikut di Global.asax:

protected void Application_Start(object sender, EventArgs e)
{
    ...
    string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
    bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
    int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
    JsPostfix = "";
#if !DEBUG
    JsPostfix += ".min";
#endif      
    JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
    if (updateEveryAppStart)
    {
        Random rand = new Random();
        JsPosfix += "_" + rand.Next();
    }
    ...
}

Saya menggunakan .Ticks (lihat jawaban saya di halaman ini)
Ravi Ram

5

Praktik umum saat ini adalah untuk menghasilkan kode hash konten sebagai bagian dari nama file untuk memaksa browser terutama IE untuk memuat kembali file javascript atau file css.

Sebagai contoh,

penjaja. a7561fb0e9a071baadb9 .js
utama. b746e3eb72875af2caa9 .js

Pada umumnya pekerjaan untuk alat bantu bangun seperti webpack. Berikut ini detail lebih lanjut jika ada yang ingin mencoba jika Anda menggunakan webpack.


4

Jika Anda membuat halaman yang menautkan ke file JS solusi sederhana menambahkan cap waktu modifikasi file terakhir ke link yang dihasilkan.

Ini sangat mirip dengan jawaban Huppie, tetapi berfungsi dalam sistem kontrol versi tanpa penggantian kata kunci. Ini juga lebih baik daripada menambahkan waktu saat ini, karena itu akan mencegah caching bahkan ketika file tidak berubah sama sekali.


Saya suka solusi ini, karena ini paling mudah untuk dipertahankan. Jika Anda memperbarui file .js, hanya itu yang perlu Anda lakukan. Tidak perlu juga memperbarui referensi ke file, karena kode Anda akan menambahkan stempel waktu terakhir yang diperbarui secara otomatis.
NL3294

3

Fungsi getScript jQuery juga dapat digunakan untuk memastikan bahwa file js memang dimuat setiap kali halaman dimuat.

Beginilah cara saya melakukannya:

$(document).ready(function(){
    $.getScript("../data/playlist.js", function(data, textStatus, jqxhr){
         startProgram();
    });
});

Periksa fungsinya di http://api.jquery.com/jQuery.getScript/

Secara default, $ .getScript () menetapkan pengaturan cache menjadi false. Ini menambahkan parameter kueri timestamped ke URL permintaan untuk memastikan bahwa browser mengunduh skrip setiap kali diminta.


8
Kita perlu melakukan cache file jika tidak ada perubahan yang terjadi.
Leo Lee

3

Dalam PHP :

function latest_version($file_name){
    echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name);
}

Dalam HTML :

<script type="text/javascript" src="<?php latest_version('/a-o/javascript/almanacka.js'); ?>">< /script>

Bagaimana itu bekerja:

Dalam HTML, tulis filepathdan beri nama seperti yang Anda lakukan, tetapi hanya dalam fungsi. PHP mendapatkan filetimefile dan mengembalikan filepath+name+"?"+timeperubahan terbaru


3

Kami telah membuat SaaS untuk pengguna dan memberi mereka skrip untuk dilampirkan di halaman situs web mereka, dan itu tidak mungkin untuk melampirkan versi dengan skrip karena pengguna akan melampirkan skrip ke situs web mereka untuk fungsionalitas dan saya tidak bisa memaksa mereka untuk mengubah versi setiap kali kami memperbarui skrip

Jadi, kami menemukan cara untuk memuat versi skrip yang lebih baru setiap kali pengguna memanggil skrip asli

tautan skrip yang diberikan kepada pengguna

<script src="https://thesaasdomain.com/somejsfile.js" data-ut="user_token"></script>

file skrip

if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) {
   init();
} else {
   loadScript("https://thesaasdomain.com/somejsfile.js?" + guid());
}

var loadscript = function(scriptURL) {
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = scriptURL;
   head.appendChild(script);
}

var guid = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

var init = function() {
    // our main code
}

Penjelasan:

Pengguna telah melampirkan skrip yang diberikan kepada mereka di situs web mereka dan kami memeriksa token unik yang dilampirkan dengan skrip ada atau tidak menggunakan pemilih jQuery dan jika tidak, muat secara dinamis dengan token (atau versi) yang lebih baru

Ini memanggil skrip yang sama dua kali yang bisa menjadi masalah kinerja, tetapi ini benar-benar memecahkan masalah memaksa skrip untuk tidak memuat dari cache tanpa menempatkan versi di tautan skrip aktual yang diberikan kepada pengguna atau klien

Penafian: Jangan gunakan jika kinerja merupakan masalah besar dalam kasus Anda.


2

Dalam asp.net mvc Anda dapat menggunakan @ DateTime.UtcNow.ToString () untuk nomor versi file js. Nomor versi otomatis berubah dengan tanggal dan Anda memaksa browser klien untuk menyegarkan secara otomatis file js. Saya menggunakan metode ini dan ini bekerja dengan baik.

<script src="~/JsFilePath/JsFile.js?v=@DateTime.UtcNow.ToString()"></script>

Seperti solusi yang disarankan lainnya, ini akan menyebabkan file tidak pernah di-cache, yang biasanya tidak diinginkan. Selama tidak ada perubahan yang dilakukan pada file, Anda mungkin ingin klien menggunakan versi yang di-cache daripada mengunduh file yang tidak berubah lagi setiap kali.
Philip Stratford

Anda dapat menggunakan kode di bawah ini untuk alasan Anda, file cache dengan nomor versi <script src = "~/JsFilePath/JsFile.js?v=@GetAppVersionNumber ()"> </script>
dragonal

2

location.reload (true);

lihat https://www.w3schools.com/jsref/met_loc_reload.asp

Saya secara dinamis memanggil baris kode ini untuk memastikan bahwa javascript telah diambil kembali dari server web alih-alih dari cache browser untuk menghindari masalah ini.


Menambahkan onload="location.reload();"ke formulir saya memungkinkan saya mendapatkan JS baru setelah penyegaran alih-alih meluncurkan kembali halaman saya. Ini solusi yang jauh lebih elegan. Terima kasih!
ZX9

Terima kasih, bisa menggunakan ini dengan tanda centang jika ip dikenali tetapi belum digunakan untuk masuk karena pembaruan terakhir melakukan ini pada halaman indeks setelah pengguna masuk awal.
Fi Horan

onload = "location.reload (true);" Di atas tidak bekerja untuk saya (menggunakan labu dan versi Chrome saat ini) juga: w3schools.com/jsref/met_loc_reload.asp
aspiringGuru

1

Salah satu solusinya adalah menambahkan string kueri dengan cap waktu di dalamnya ke URL saat mengambil sumber daya. Ini memanfaatkan fakta bahwa browser tidak akan menembolok sumber daya yang diambil dari URL dengan string kueri di dalamnya.

Anda mungkin tidak ingin browser untuk tidak men-cache sumber daya ini sama sekali; kemungkinan Anda ingin di-cache, tetapi Anda ingin browser mengambil versi baru dari file ketika itu tersedia.

Solusi yang paling umum tampaknya adalah menyematkan stempel waktu atau nomor revisi dalam nama file itu sendiri. Ini sedikit lebih banyak pekerjaan, karena kode Anda perlu dimodifikasi untuk meminta file yang benar, tetapi itu berarti bahwa, misalnya versi 7 dari snazzy_javascript_file.js(yaitu snazzy_javascript_file_7.js) Anda di-cache di browser hingga Anda merilis versi 8, dan kemudian kode Anda berubah menjadi ambil snazzy_javascript_file_8.jsalih.


1

Keuntungan menggunakan file.js?V=1over fileV1.jsadalah bahwa Anda tidak perlu menyimpan beberapa versi file JavaScript di server.

Masalah yang saya lihat file.js?V=1adalah bahwa Anda mungkin memiliki kode dependen dalam file JavaScript lain yang rusak saat menggunakan versi baru dari utilitas perpustakaan.

Demi kompatibilitas ke belakang, saya pikir jauh lebih baik menggunakan jQuery.1.3.jshalaman baru Anda dan membiarkan halaman yang ada digunakan jQuery.1.1.js, sampai Anda siap untuk meningkatkan halaman yang lebih tua, jika perlu.


1

Gunakan GETvariabel versi untuk mencegah caching browser.

Menambah ?v=AUTO_INCREMENT_VERSIONbagian akhir url Anda mencegah cache browser - menghindari skrip cache apa pun dan semua.


1

Kolega saya baru saja menemukan referensi ke metode itu setelah saya memposting (mengacu pada css) di http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/ . Senang melihat bahwa orang lain menggunakannya dan tampaknya berhasil. Saya berasumsi pada titik ini bahwa tidak ada cara yang lebih baik daripada mencari-ganti untuk menambah "nomor versi" ini di semua tag skrip?



1

Penghilang Tembolok di ASP.NET Core melalui tag helper akan menangani ini untuk Anda dan memungkinkan peramban Anda menyimpan skrip / css yang di-cache hingga file berubah. Cukup tambahkan tag helper asp-append-version = "true" ke skrip (js) atau tag tautan (css) Anda:

<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>

Dave Paquette memiliki contoh dan penjelasan yang bagus tentang penghilang cache di sini (bagian bawah halaman) Penghilang Tembolok


Apakah ini tidak berfungsi di ASP.NET biasa? Saya mencoba menambahkan asp-append-version ke tag skrip saya dan semua yang dilihat browser adalah tag skrip persis seperti yang muncul di sumber, termasuk atribut asp-append-versi.
tolsen64

Ini adalah atribut .NET Core yang terkait dengan Tag Helpers. Itu menambahkan nama skrip dengan versi sehingga server / browser selalu melihat versi terbaru dan unduhan
ccherwin

0

Solusi paling sederhana? Jangan biarkan cache browser sama sekali. Tambahkan waktu saat ini (dalam ms) sebagai kueri.

(Anda masih dalam versi beta, jadi Anda bisa membuat alasan yang masuk akal untuk tidak mengoptimalkan kinerja. Tapi YMMV di sini.)


13
IMHO ini adalah solusi yang buruk. Bagaimana jika Anda tidak berada di BETA dan Anda mendorong pembaruan penting?
d -_- b

0

Satu cara sederhana. Edit htaccess

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC]
RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L]

Hal ini menyebabkan pengalihan yang merupakan solusi yang suboptimal, tetapi berfungsi baik.
twicejr

0

Di bawah ini bekerja untuk saya:

<head>
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
<meta http-equiv="cache-control" content="max-age=0" />
<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" />
</head>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.