Tarayıcı, önbelleğe alınmış CSS / JS dosyalarını yeniden yüklemeye nasıl zorlanır?


993

Bazı tarayıcıların (özellikle Firefox ve Opera) tarayıcı oturumları arasında bile .css ve .js dosyalarının önbelleğe alınmış kopyalarını kullanırken çok gayretli olduklarını fark ettim . Bu, bu dosyalardan birini güncellediğinizde bir soruna neden olur, ancak kullanıcının tarayıcısı önbelleğe alınmış kopyayı kullanmaya devam eder.

Soru şudur: Kullanıcının tarayıcısını değiştiğinde dosyayı yeniden yüklemeye zorlamanın en zarif yolu nedir?

İdeal olarak, çözüm, tarayıcıyı sayfayı her ziyarette dosyayı yeniden yüklemeye zorlamaz. Kendi çözümümü yanıt olarak göndereceğim, ancak daha iyi bir çözüm olup olmadığını merak ediyorum ve oylarınızın karar vermesine izin vereceğim.

Güncelleme :

Bir süre burada tartışmaya izin verdikten sonra, John Millikin ve da5id'in önerisinin yararlı olduğunu gördüm . Bunun için bir terim olduğu ortaya çıktı: otomatik versiyonlama .

Aşağıda, orijinal çözümümün ve John'un önerisinin bir kombinasyonu olan yeni bir cevap gönderdim.

SCdF tarafından önerilen başka bir fikir , dosyaya sahte bir sorgu dizesi eklemek olacaktır. (Zaman damgasını otomatik olarak sahte sorgu dizesi olarak kullanmak için bazı Python kodları pi ile gönderilmiştir .) Ancak, tarayıcının bir dosyayı sorgu dizesi ile önbelleğe alıp almayacağı konusunda bazı tartışmalar vardır. (Tarayıcının dosyayı önbelleğe almasını ve gelecekteki ziyaretlerde kullanmasını istiyoruz. Yalnızca dosya değiştiğinde dosyayı tekrar getirmesini istiyoruz.)

Sahte bir sorgu dizesi ile ne olduğu belli olmadığından, bu yanıtı kabul etmiyorum.


Ben önbelleğe dosyalarla hiç sorun yaratmazlar benim .htaccess bu var ve: ExpiresActive On ExpiresDefault "modification".
Frank Conijn

2
Dosyanın URL'sine sürüm bilgisi eklemenin en iyi yol olduğunu kesinlikle kabul ediyorum. Herkes için her zaman çalışır. Ancak, onu kullanmıyorsanız ve sadece bir CSS veya JS dosyasını ara sıra kendi tarayıcınıza yeniden yüklemeniz gerekiyorsa ... sadece kendi sekmesinde açın ve SHIFT-reload (veya CTRL-F5) tuşuna basın! Aynı şeyi JS kullanarak bir dosyayı (gizli) iframe'e yükleyerek, yüklenene kadar bekleyip arayarak da etkili bir şekilde yapabilirsiniz iframe.contentWindow.location.reload(true). Stackoverflow.com/a/22429796/999120 yöntemine (4) bakın - bu görüntülerle ilgilidir, ancak aynı şey geçerlidir.
Doin

2
Bu sorunun sorulduğu ve o zamandan beri güncellendiği için gerçekten minnettarım. Cevaplarda ne beklemem gerektiğini tamamen anlattı. Bundan sonra sorularımda bu yaklaşımı takip edeceğim. Şerefe!
rd22

Yanıtlar:


455

Güncelleme: John Millikin ve da5id'in önerilerini içerecek şekilde yeniden yazıldı . Bu çözüm PHP ile yazılmıştır, ancak diğer dillere kolayca uyarlanmalıdır.

Güncelleme 2: gelen yorumları birleştirilerek Nick Johnson orijinal olduğunu .htaccessregex gibi dosyalarla sorunlara neden olabilir json-1.3.js. Çözüm, yalnızca sonunda tam 10 basamak varsa yeniden yazmaktır. (Çünkü 10 basamak 9/9/2001 - 11/20/2286 arasındaki tüm zaman damgalarını kapsar.)

İlk olarak, .htaccess içinde aşağıdaki yeniden yazma kuralını kullanıyoruz:

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]

Şimdi, aşağıdaki PHP fonksiyonunu yazıyoruz:

/**
 *  Given a file, i.e. /css/base.css, replaces it with a string containing the
 *  file's mtime, i.e. /css/base.1221534296.css.
 *  
 *  @param $file  The file to be loaded.  Must be an absolute path (i.e.
 *                starting with slash).
 */
function auto_version($file)
{
  if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
    return $file;

  $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
  return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}

Şimdi, CSS'nizi nereye eklerseniz yerleştirin, buradan değiştirin:

<link rel="stylesheet" href="/css/base.css" type="text/css" />

Buna:

<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />

Bu şekilde, bağlantı etiketini bir daha asla değiştirmek zorunda kalmazsınız ve kullanıcı her zaman en son CSS'yi görür. Tarayıcı CSS dosyasını önbelleğe alabilir, ancak CSS'nizde herhangi bir değişiklik yaptığınızda tarayıcı bunu yeni bir URL olarak görür, bu nedenle önbelleğe alınmış kopyayı kullanmayacaktır.

Bu, resimler, favicons ve JavaScript ile de çalışabilir. Temel olarak dinamik olarak oluşturulmayan herhangi bir şey.


16
Dosya adı değişikliği (base.1221534296.css) yerine sürümlendirme için bir parametre (base.css? V = 1221534296) kullanmam dışında, kendi statik içerik sunucum tamamen aynı şeyi yapıyor. Yolunuzun biraz daha verimli olabileceğinden şüpheleniyorum. Çok havalı.
Jens Roland

4
@Kip: Çok kaygan bir çözüm. URL yeniden yazmanın, sadece güzel görünen URL'lerden çok daha fazlası vardır.
James P.

37
Bununla ilgili bir sorun görüyorum ki, dosya sistemine birçok kez erişiyor - tam olarak - bağlantı sayısı * istek / sn sayısı ... sizin için bir sorun olabilir veya olmayabilir.
Tomáš Fejfar

3
@AlixAxel: Hayır, parametre değiştiğinde tarayıcılar yeniden alır, ancak bazı genel proxy'ler URL parametrelerine sahip dosyaları önbelleğe almaz, bu nedenle en iyi uygulama sürümü yola dahil etmektir. Ve mod_rewrite yükü, WPO'daki diğer tüm performans darboğazına kıyasla miniktir
Jens Roland

8
İlk file_existskontrol gerçekten gerekli mi? filemtimebaşarısızlık durumunda false döndürür, öyleyse neden filemtime değerini bir değişkene atamaz ve dosyayı yeniden adlandırmadan önce yanlış olup olmadığını kontrol etmezsiniz? Bu, gerçekten toplayacak olan gereksiz bir dosya işlemini azaltacaktır.
Gavin

184

Basit İstemci Tarafı Tekniği

Genel olarak, önbellekleme iyidir .. Yani, bir web sitesi geliştirirken sorunu kendiniz çözüp çözmediğinize veya bir üretim ortamında önbelleği kontrol etmeye çalışıp çalışmadığınıza bağlı olarak birkaç teknik vardır.

Web sitenize gelen genel ziyaretçiler, siteyi geliştirirken yaşadığınız deneyime sahip olmayacaktır. Ortalama bir ziyaretçi siteye daha az sıklıkta geldiğinden (bir Google veya hi5 Ağınız olmadıkça her ay yalnızca birkaç kez), dosyalarınızı önbellekte bulundurma olasılığı daha düşüktür ve bu yeterli olabilir. Tarayıcıya yeni bir sürümü zorlamak istiyorsanız, isteğe her zaman bir sorgu dizesi ekleyebilir ve büyük değişiklikler yaptığınızda sürüm numarasını yükseltebilirsiniz:

<script src="/myJavascript.js?version=4"></script>

Bu, herkesin yeni dosyayı almasını sağlayacaktır. Tarayıcı önbellekte bir kopya olup olmadığını belirlemek için dosyanın URL'sine baktığı için çalışır. Sunucunuz sorgu dizesiyle hiçbir şey yapmayacak şekilde ayarlanmamışsa, yok sayılır, ancak ad tarayıcıya yeni bir dosya gibi görünür.

Öte yandan, bir web sitesi geliştiriyorsanız, geliştirme sürümünüzde her değişiklik yaptığınızda sürüm numarasını değiştirmek istemezsiniz. Bu sıkıcı olurdu.

Sitenizi geliştirirken, otomatik olarak bir sorgu dizesi parametresi oluşturmak iyi bir yöntem olacaktır:

<!-- Development version: -->
<script>document.write('<script src="/myJavascript.js?dev=' + Math.floor(Math.random() * 100) + '"\><\/script>');</script>

İsteğe bir sorgu dizesi eklemek bir kaynağı sürümlendirmenin iyi bir yoludur, ancak basit bir web sitesi için bu gereksiz olabilir. Ve unutmayın, önbellekleme iyi bir şeydir.

Ayrıca, tarayıcının dosyaları önbellekte tutmaya cimri olmadığını da belirtmek gerekir. Tarayıcıların bu tür şeyler için politikaları vardır ve genellikle HTTP spesifikasyonunda belirtilen kurallara göre oynarlar. Bir tarayıcı bir sunucuya istekte bulunduğunda, yanıtın bir kısmı EXPIRES üstbilgisidir .. tarayıcıya önbellekte ne kadar süreyle saklanması gerektiğini bildiren bir tarih. Tarayıcı aynı dosya için bir sonraki istekle karşılaştığında, önbellekte bir kopyası olduğunu görür ve kullanılıp kullanılmayacağına karar vermek için EXPIRES tarihine bakar.

İster inanın ister inanmayın, aslında o tarayıcı önbelleğini bu kadar kalıcı yapan sunucunuz. Sunucu ayarlarınızı yapabilir ve EXPIRES üstbilgilerini değiştirebilirsiniz, ancak yukarıda yazdığım küçük teknik, muhtemelen bu konuda daha basit bir yöntemdir. Önbelleğe alma iyi olduğu için, genellikle bu tarihi geleceğe ("Uzak Gelecekte Süre Sonu Başlığı") ayarlamak ve bir değişikliği zorlamak için yukarıda açıklanan tekniği kullanmak istersiniz.

HTTP hakkında daha fazla bilgi veya bu isteklerin nasıl yapıldığını merak ediyorsanız, iyi bir kitap Steve Souders'ın "Yüksek Performanslı Web Siteleri" dir. Konuya çok iyi bir giriş.


3
Javascript ile sorgu dizesi oluşturmanın hızlı hilesi aktif geliştirme sırasında harika çalışıyor. PHP ile aynı şeyi yaptım.
Alan Turing,

2
Bu, orijinal posterin istenen sonucunu elde etmenin en kolay yoludur. Sayfayı her yüklediğinizde .css veya .js dosyasının yeniden yüklenmesini zorlamak istiyorsanız mod_rewrite yöntemi iyi çalışır. Bu yöntem, siz dosyayı gerçekten değiştirip yeniden yüklemeyi gerçekten zorlayana kadar önbelleğe almayı sağlar.
scott80109

@keparo, bu sayfaları el ile değiştireceğim eğer bir ay sürecek tüm sayfalarda bol miktarda jquery var. Her sayfaya kodlamadan çözmeme yardımcı olabilirseniz.
kraker

1
<link href='myCss.css?dev=14141'...>
Kullandığımda bu CSS'im

3
Bu uygun bir çözüm değildir. Çok sayıda tarayıcı, üzerinde bir sorgu dizesi olan her şeyi önbelleğe almayı reddeder. Statik içeriğe yapılan başvurularda sorgu dizeleriniz varsa Google, GTMetrix ve benzer araçların bir bayrak oluşturmasının nedeni budur. Kesinlikle geliştirme için iyi bir çözüm olsa da, kesinlikle üretim için bir çözüm değildir. Ayrıca, tarayıcı sunucuyu değil, önbelleğe almayı denetler. Sunucu, ne zaman yenilenmesi gerektiğini ÖNERİR; bir tarayıcı sunucuyu dinlemek zorunda DEĞİLDİR (ve çoğu zaman duymaz). Mobil cihazlar bunun en iyi örneğidir.
Nate I

113

Google'ın apache için mod_pagespeed eklentisi sizin için otomatik sürümlendirme yapacaktır. Gerçekten kaygan.

HTML'yi web sunucusundan çıkarken ayrıştırır (PHP, raylar, python, statik HTML - herhangi bir şeyle çalışır) ve bir kimlik kodu içerecek şekilde CSS, JS, resim dosyalarına bağlantıları yeniden yazar. Üzerinde çok uzun bir önbellek kontrolü bulunan değiştirilmiş URL'lerdeki dosyaları sunar. Dosyalar değiştiğinde, tarayıcı otomatik olarak URL'leri değiştirir, böylece tarayıcının yeniden getirmesi gerekir. Temel olarak, kodunuzda herhangi bir değişiklik yapmadan çalışır. Hatta çıkışta kodunuzu küçültebilir.


1
Bu harika, ama yine de beta sürümündedir. Kurumsal hizmet için kullanılabilir mi?
Sanghyun Lee

26
Bu açıkça bir tarayıcı sorunu olduğunda YANLIŞ (kaynak ile otomatik uğraş). Bize (geliştiriciler) gerçek bir beyin silme-yenileme verin: <ctrl> + F5
T4NK3R

25
mod_pagespeed, html / css / js için tamamen otomatik bir derleme / derleme adımına işlevsel olarak eşdeğerdir. Yapı sistemlerinin kendiliğinden yanlış olduğunu veya tamamen otomatik olmasıyla ilgili yanlış bir şey olduğunu düşünen ciddi geliştiricileri bulmak için zorlanacağınızı düşünüyorum. Temiz bir yapı benzetmesi mod_pagespeed'in önbelleğini temizlemektir: code.google.com/p/modpagespeed/wiki/… ?
Leopd

3
@ T4NK3R mod_pagespeed, önbellek yönetimi yapmak için kaynağınızla hiçbir şey yapmak zorunda değildir, basitçe minyatür gibi şeylere yardımcı olabileceğinden bahsedilmiştir . "YANLIŞ" olup olmadığını, tamamen öznel. Sizin için yanlış olabilir, ancak bu içgüdüsel olarak kötü olduğu anlamına gelmez .
Madbreaks

2
Nginx ile de çalışıyor, ancak kaynaktan oluşturmak zorundasınız: developers.google.com/speed/pagespeed/module/…
Rohit

93

Sürümü manuel olarak değiştirmek yerine, gerçek CSS dosyasının MD5 karmasını kullanmanızı öneririm.

URL'niz şöyle bir şey olurdu

http://mysite.com/css/[md5_hash_here]/style.css

Yeniden yazma kuralını karmayı çıkarmak için kullanabilirsiniz, ancak avantajı, önbellek politikanızı "sonsuza kadar önbellek" olarak ayarlayabilmenizdir, çünkü URL aynıysa, dosyanın değişmediği anlamına gelir.

Daha sonra, dosyanın karmasını hesaplayacak ve etiketinizi güncelleyecek basit bir kabuk komut dosyası yazabilirsiniz (muhtemelen dahil etmek için ayrı bir dosyaya taşımak istersiniz).

Bu komut dosyasını CSS her değiştiğinde çalıştırın ve iyisiniz. Tarayıcı SADECE değiştirildiklerinde dosyalarınızı yeniden yükleyecektir. Bir düzenleme yapar ve ardından geri alırsanız, ziyaretçilerinizin yeniden indirmemesi için hangi sürüme geri dönmeniz gerektiğini anlamakta herhangi bir acı yoktur.


1
ne yazık ki nasıl uygulanacağını bilmiyorum. Tavsiye lütfen ... daha fazla ayrıntı ...
Michael Phelps

Kabuk, yakut vb. Bir uygulama harika olurdu
Peter

3
Çok güzel bir çözüm .. ama her dosya ziyaretinde (css, js, resimler, html..etc) her dosya isteğinde (hash) dosyanın karma değerini hesaplamak için kaynak tüketen olduğunu düşünüyorum.
DeepBlue

Bu, yudum, homurdanma veya web paketi ile js veya css demetini kullananlar için standart bir çözümdür, uygulama her çözüm için farklıdır, ancak dosyalarınızı bir derleme adımı olarak
dağıtmak

@DeepBlue - yanıt "CSS her değiştiğinde bu komut dosyasını çalıştır" diyor . Bu her sayfa ziyaretinde DEĞİLDİR. OTOH Cevap büyük ayrıntılar çıkarıyor - değişen karma URL'nin nasıl bir parçası haline geliyor? Bilmiyorum ...
ToolmakerSteve

70

Bu çözümü uygulamak için neden bu kadar çok acı çektiğinizden emin değilim.

Dosyanın değiştirilmiş zaman damgasını alıp dosyaya sorgu dizesi olarak eklerseniz tek yapmanız gereken

PHP i olarak yapardı:

<link href="mycss.css?v=<?= filemtime('mycss.css') ?>" rel="stylesheet">

filemtime, değiştirilmiş zaman damgasını döndüren bir PHP işlevidir.


Sadece kullanabilirsiniz mycss.css?1234567890.
Gavin

3
Çok zarif, ancak biraz değiştirmiş olsam da <link rel="stylesheet" href="mycss.css?<?php echo filemtime('mycss.css') ?>"/>, URL'leri GET değişkenleriyle (önerilen formatta)
önbelleğe almayla

benim son yorum daha da, ben wordpress kullanır ?ver=böylece kim bilir gördüm !
luke_mclachlan

Harika bir çözüm. Ayrıca benim için filemtime tam bir etki alanı adı (FQDN) için işe yaramadı buldum, bu yüzden href kısmı için FQDN ve filemtime kısmı için $ _SERVER ["DOCUMENT_ROOT"] kullandım. EX: <link rel = "stil sayfası" href = "http: //theurl/mycss.css? V = <? Php echo filemtime ($ _ SERVER [" DOCUMENT_ROOT "]. '/Mycss.css')?>" />
rrtx2000

Çok teşekkürler. Basit ve iyi. İşte Python'da: progpath = os.path.dirname (sys.argv [0]) def versionize (dosya): timestamp = os.path.getmtime ('% s /../ web /% s'% (progpath , dosya)) dönüş '% s? v =% s'% (dosya, zaman damgası) print <link href = "% s" rel = "stylesheet" '' type = "text / css" /> '\% versionize ( 'css / main.css')
dlink

52

Sadece ?foo=1234css / js içe aktarımınızın sonuna koyabilirsiniz , 1234'ü istediğiniz gibi değiştirin. Örnek olarak SO html kaynağına bir göz atın.

Buradaki fikir? parametreler yine de istek üzerine atılır / yoksayılır ve yeni bir sürüm yayınladığınızda bu sayıyı değiştirebilirsiniz.


Not: Bunun önbelleğe almayı tam olarak nasıl etkilediği konusunda bazı tartışmalar vardır. Bunun genel amacı, parametreli veya parametresiz GET isteklerinin önlenebilir olması gerektiğinden , yukarıdaki çözümün çalışması gerektiğine inanıyorum.

Ancak, spesifikasyonun o bölümüne ve kullanıcının kullandığı tarayıcıya uyup uymayacağına karar vermek hem web sunucusuna bağlıdır, çünkü hemen devam edip yeni bir sürüm isteyebilir.


Saçmalık. Sorgu dizesi (aka. GET parametreleri) URL'nin bir parçasıdır. Önbelleklenebilirler ve önbelleğe alınırlar. Bu iyi bir çözüm.
troelskn

9
@troelskn: HTTP 1.1 spesifikasyonu aksini söyler (sorgu parametreleri ile GET ve HEAD istekleriyle ilgili olarak): önbellek, sunucu açık bir sona erme süresi sağlamadığı sürece bu URI'lara verilen yanıtları taze olarak KULLANMAMALIDIR. Bkz. W3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.9
Michael Johnson

4
Ben tüm büyük tarayıcılar ile sürüm dizesi sorgu dizesi tür denedim ve onlar, önbellek özellikleri, ya da değil. Ancak, yine de sorgu dizelerini kötüye kullanmadan style.TIMESTAMP.css biçimini kullanmanın daha iyi olduğunu düşünüyorum, çünkü yine de proxy yazılımının önbelleğe alınması dosyayı önbelleğe ALMAYACAKTIR.
Tomas Andrle

34
Hangi nedenle olursa olsun, Stackoverflow'un kendisi sorgu dizesi yöntemini kullandığını belirtmek gerekir.
jason

2
? = Parametresi kullanmanın, parametre değiştiğinde tarayıcıların önbelleğe alınmış dosyayı yeniden getirmeyeceğini doğruladınız. Tek yol, dosya adını sunucu tarafından sunucu tarafından Kip
arunskrish

41

Bunun "otomatik versiyonlama" olduğunu duydum. En yaygın yöntem, statik dosyanın mtime değerini URL'nin herhangi bir yerine dahil etmek ve yeniden yazma işleyicileri veya URL confs kullanarak çıkartmaktır:

Ayrıca bakınız:


3
Teşekkürler, sanırım bu, fikrimin tartışıldığı başka bir durumdu, ne denildiğini bilmiyordum, bu yüzden Google aramalarında asla bulamadım.
Kip

27

30 kadar mevcut cevap yaklaşık 2008 web sitesi için büyük tavsiye vardır. Bununla birlikte, modern, tek sayfalık bir uygulama (SPA) söz konusu olduğunda, bazı temel varsayımları yeniden düşünmenin zamanı gelmiş olabilir… özellikle web sunucusunun yalnızca tek, en son sürümüne hizmet etmesi arzu edilir dosya.

Tarayıcınıza bir SPA'nın M sürümünü yükleyen bir kullanıcı olduğunuzu düşünün :

  1. CD kanalınız uygulamanın yeni N sürümünü sunucuya dağıtır
  2. Almak için sunucuya bir XHR gönderen SPA içinde geziniyorsunuz /some.template
    • (Tarayıcınız sayfayı yenilemedi, bu yüzden hala M sürümünü çalıştırıyorsunuz )
  3. Sunucu aşağıdakilerin içeriğiyle yanıt verir /some.template- şablonun M veya N sürümünü döndürmesini istiyor musunuz?

M ve N/some.template sürümleri arasında değiştirilen biçim (veya dosya yeniden adlandırılmış veya herhangi bir şekilde) , muhtemelen şablonun N sürümünün ayrıştırıcının eski M sürümünü çalıştıran tarayıcıya gönderilmesini istemezsiniz . †

Web uygulamaları iki koşul karşılandığında bu sorunla karşılaşır:

  • Kaynaklar, ilk sayfa yüklemesinden bir süre sonra eşzamansız olarak isteniyor
  • Uygulama mantığı, kaynak içeriğe ilişkin (gelecekteki sürümlerde değişebilecek) şeyler varsayar

Uygulamanızın birden çok sürümü paralel olarak sunması gerektiğinde, önbelleğe alma ve "yeniden yükleme" işlemlerini çözmek önemsiz hale gelir:

  1. Sürüm bilgisi dirs içine tüm site dosyalarını yükleyin: /v<release_tag_1>/…files…,/v<release_tag_2>/…files…
  2. Tarayıcıların dosyaları sonsuza kadar önbelleğe almasını sağlamak için HTTP üstbilgilerini ayarlama
    • (Ya da daha iyisi, her şeyi bir CDN'ye koyun)
  3. Tümünü <script>ve <link>etiketleri, vb., Sürümlendirilmiş dizinlerden birinde bu dosyayı işaret edecek şekilde güncelleyin

Sunucu tarafı veya istemci tarafı kodunuzdaki her URL için bir URL oluşturucu çağırmayı gerektirebileceğinden, bu son adım zor geliyor. Veya <base>etiketi akıllıca kullanabilir ve mevcut sürümü tek bir yerden değiştirebilirsiniz.

† Bunun bir yolu, yeni bir sürüm yayınlandığında tarayıcıyı her şeyi yeniden yüklemeye zorlamak konusunda agresif olmaktır. Ancak, devam eden işlemlerin tamamlanmasına izin vermek adına, paralel olarak en az iki sürümü desteklemek en kolay olabilir: v-akımı ve v-önceki.


Michael - yorumunuz çok alakalı. Burada tam olarak benim SPA için bir çözüm bulmaya çalışırken cam. Bazı işaretçilerim vardı, ama kendim bir çözüm bulmalıydım. Sonunda, ben ne geldi ile gerçekten mutlu oldu, bu yüzden bir blog yazısı ve bu soruya bir cevap (kod dahil) yazdım.
İşaretçiler

Harika yorum. İnsanlar sanki bu marjinal bir durum gibi SPA'ların yeni sorunları caydırma olmadan web sitelerini önbellek sorunları için gerçek bir çözüm olarak önbellek bozma ve HTTP önbellekleme hakkında konuşmaya devam ederken anlayamıyorum.
David Casillas

1
Mükemmel yanıt ve kesinlikle ideal strateji! Ve baseetiketten bahsettiğiniz için bonus puanlar ! Eski kodu desteklemeye gelince: bu her zaman bir olasılık değil, her zaman iyi bir fikir değildir. Kodun yeni sürümleri, bir uygulamanın diğer parçalarındaki değişikliklerin kırılmasını destekleyebilir veya acil durum düzeltmeleri, güvenlik açığı yamaları vb. İçerebilir. Bu stratejiyi henüz kendim uygulayamadım, ancak her zaman genel mimarinin, dağıtımların eski bir sürümü etiketlemesine izin vermesi obsoleteve bir sonraki eşzamansız çağrı yapıldığında (veya WebSockets üzerinden tüm oturumları zorla yetkisini kaldırması için) izin vermesi gerektiğini hissettim ).
Jonny Asmar

Tek sayfa uygulamaları ile ilgili iyi düşünülmüş bir cevap görmek güzel.
Nate I

Daha fazla bilgi aramak istiyorsanız bu "mavi-yeşil dağıtım" dır.
Fil

15

Foo.css? Version = 1 kullanmayın! Tarayıcıların GET değişkenlerine sahip URL'leri önbelleğe alması gerekmez. Http://www.thinkvitamin.com/features/webapps/serving-javascript-fast'a göre , IE ve Firefox bunu görmezden geliyor, Opera ve Safari yok! Bunun yerine, foo.v1234.css dosyasını kullanın ve sürüm numarasını çıkarmak için yeniden yazma kurallarını kullanın.


1
Her şeyden önce tarayıcılar önbelleğe almaz, bu bir HTTP işlevidir. Http neden bir URI'nin yapısına önem veriyor? HTTP önbelleklemesinin, bir sorgu dizesiyle öğeleri önbelleğe almaması için bir URI'nin semantiğini anlaması gerektiğini bildiren bir spesifikasyona resmi bir başvuru var mı?
AnthonyWJones

13
Nesneleri önbelleğe alma işlevini içeren bir web tarayıcısı (tarayıcınızın önbellek dizinini kontrol edin). HTTP, sunuculardan istemcilere (proxy'ler, tarayıcılar, örümcekler vb.) Önbellek kontrolü öneren yönergeler içeren bir protokoldür.
tzot

13

Laravel'de (PHP) bunu net ve zarif bir şekilde yapabiliriz (dosya değiştirme zaman damgasını kullanarak):

<script src="{{ asset('/js/your.js?v='.filemtime('js/your.js')) }}"></script>

CSS için de benzer

<link rel="stylesheet" href="{{asset('css/your.css?v='.filemtime('css/your.css'))}}">

Örnek html çıkışı ( Unix zaman damgasıfilemtime olarak dönüş süresi )

<link rel="stylesheet" href="assets/css/your.css?v=1577772366">

html'de bu komutun çıktısı nedir? Ve ne gibi v sadece versiyonlarını yenilemek gerekiyorsa = 3, v = 4 vb? -? Yük css her kullanıcıya tarayıcısı zorlamayın mu web sitesine girer
Gediminas

filemtime : "Bu işlev, bir dosyanın veri bloklarının yazıldığı zamanı, yani dosyanın içeriğinin değiştirildiği zamanı döndürür." src: php.net/manual/tr/function.filemtime.php
Kamil Kiełczewski

11

RewriteRule, sonunda nokta gösterimi sürümü içeren js veya css dosyaları için küçük bir güncellemeye ihtiyaç duyar. Örneğin, json-1.3.js.

Normal ifadeye bir nokta negatifleme sınıfı [^.] Ekledim .number. yoksayılır.

RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]

2
Giriş için teşekkürler! Bu yazıyı yazdığımdan beri ben de bu işten yanmıştım. Çözümüm yalnızca dosya adının son kısmı tam olarak on basamak içeriyorsa yeniden yazmaktı. (10 basamak 9/9/2001 - 11/20/2286 arasındaki tüm zaman damgalarını kapsar.) Cevabımı bu normal ifadeyi içerecek şekilde güncelledim:^(.*)\.[\d]{10}\.(css|js)$ $1.$2
Kip

Normal ifadeyi anlıyorum, ancak burada hangi sorunu çözdüğünüzü anlamıyorum [^.]. Ayrıca, \dbir karakter sınıfının içine yazmanın bir yararı yoktur - \d+aynı şeyi yapar. Gönderildiği gibi, deseniniz herhangi bir sayıda karakterle (açgözlü olarak), ardından değişmez bir nokta, sonra bir nokta olmayan, sonra bir veya daha fazla basamak, sonra bir nokta, sonra cssveya jsdosya adının sonu ile eşleşir. Senin numune girişi için hiçbir maç: regex101.com/r/RPGC62/1
mickmackusa

10

ASP.NET 4.5 ve sonraki sürümleri için komut dosyası paketlemesini kullanabilirsiniz .

İstek http://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81AllMyScripts paketi içindir ve v = r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81 bir sorgu dizesi çifti içerir. Sorgu dizesi v, önbellekleme için kullanılan benzersiz bir tanımlayıcı olan bir değer belirtecine sahiptir. Paket değişmediği sürece, ASP.NET uygulaması bu belirteci kullanarak AllMyScripts paketini ister. Paketteki herhangi bir dosya değişirse, ASP.NET optimizasyon çerçevesi yeni bir belirteç oluşturarak paket için tarayıcı isteklerinin en son paketi alacağını garanti eder.

Paketlemenin, ilk kez sayfa yüklemelerinde performansı minimize ederek artırmayı da içeren başka faydaları da vardır.


Lütfen bana yardım edin bundle.config dosyasında herhangi bir değişiklik yapmıyorum sadece css veya js dosyalarında değişiklik yaparak önbellek sorununu nasıl çözebilirim?
vedankita kumbhar

10

İşte saf bir JavaScript çözümü

(function(){

    // Match this timestamp with the release of your code
    var lastVersioning = Date.UTC(2014, 11, 20, 2, 15, 10);

    var lastCacheDateTime = localStorage.getItem('lastCacheDatetime');

    if(lastCacheDateTime){
        if(lastVersioning > lastCacheDateTime){
            var reload = true;
        }
    }

    localStorage.setItem('lastCacheDatetime', Date.now());

    if(reload){
        location.reload(true);
    }

})();

Yukarıdakiler, kullanıcının sitenizi en son ziyaret ettiği zamanı arayacaktır. Son ziyaret, yeni bir kod yayınlamadan önce gerçekleşmişse location.reload(true), sunucudan sayfa yenilemeyi zorlamak için kullanılır .

Ben genellikle <head>diğer ilk içerik yüklemeden önce değerlendirilir içinde ilk komut dosyası olarak bu var. Yeniden yükleme yapılması gerekiyorsa, kullanıcı tarafından farkedilemez.

Tarayıcıda son ziyaret zaman damgasını saklamak için yerel depolama kullanıyorum, ancak IE'nin eski sürümlerini desteklemek istiyorsanız karışıma çerezler ekleyebilirsiniz.


Böyle bir şey denedim, bu sadece yeniden yüklenen sayfada çalışacaktır, ancak sitenin aynı css / görüntüleri paylaşan çoklu sayfaları varsa, diğer sayfalar hala eski kaynakları kullanacaktır.
DeepBlue

9

İlginç yazı. Burada tüm cevapları okumak zorunda ben hiç "sahte" sorgu dizeleri (ki herkes neden bu kadar kullanmak için bu kadar isteksiz olduğundan emin değilim) ile herhangi bir sorun yaşamamış birlikte kombine (apache yeniden yazma kurallarına ihtiyacı ortadan kaldırır) kabul edilen cevapta olduğu gibi), sahte bir sorgu dizesi olarak CSS dosya içeriklerinin kısa bir HASH değerini (datetime yerine) hesaplamaktır.

Bu aşağıdakilerle sonuçlanır:

<link rel="stylesheet" href="/css/base.css?[hash-here]" type="text/css" />

Tabii ki datetime çözümleri de bir CSS dosyasını düzenleme durumunda işi halletmek ama bu dosya datetime değil, css dosya içeriği ile ilgili olduğunu düşünüyorum, bu yüzden neden bu karışık olsun?


8

Gelişimim için kromun harika bir çözümü olduğunu düşünüyorum.

https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload

Geliştirici araçları açıkken, yenile düğmesini uzun tıklayın ve "Önbelleği Boşalt ve Sabit Yeniden Yükle" nin üzerine geldiğinizde bırakın.

Bu benim en iyi arkadaşım ve istediğini almanın süper hafif bir yolu!


Chrome'u geliştirme ortamınız olarak kullanıyorsanız, başka bir non-invaziv çözüm önbelleği devre dışı bırakmaktır: Ayarlar dişli kutusu altında, 'Önbelleği devre dışı bırak' seçeneğini belirleyerek disk önbelleğini geçersiz kılabilirsiniz (not: DevTools görünür / açık olmalıdır bunun çalışması için).
Velojet

7

Mükemmel çözümü için Kip'e teşekkürler!

Zend_view_Helper olarak kullanmak için uzattım. Müşterim sayfasını sanal bir ana bilgisayarda çalıştırdığından, bunun için de genişlettim.

Umarım başka birine de yardımcı olur.

/**
 * Extend filepath with timestamp to force browser to
 * automatically refresh them if they are updated
 *
 * This is based on Kip's version, but now
 * also works on virtual hosts
 * @link http://stackoverflow.com/questions/118884/what-is-an-elegant-way-to-force-browsers-to-reload-cached-css-js-files
 *
 * Usage:
 * - extend your .htaccess file with
 * # Route for My_View_Helper_AutoRefreshRewriter
 * # which extends files with there timestamp so if these
 * # are updated a automatic refresh should occur
 * # RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
 * - then use it in your view script like
 * $this->headLink()->appendStylesheet( $this->autoRefreshRewriter($this->cssPath . 'default.css'));
 *
 */
class My_View_Helper_AutoRefreshRewriter extends Zend_View_Helper_Abstract {

    public function autoRefreshRewriter($filePath) {

        if (strpos($filePath, '/') !== 0) {

            // path has no leading '/'
            return $filePath;
        } elseif (file_exists($_SERVER['DOCUMENT_ROOT'] . $filePath)) {

            // file exists under normal path
            // so build path based on this
            $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $filePath);
            return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
        } else {

            // fetch directory of index.php file (file from all others are included)
            // and get only the directory
            $indexFilePath = dirname(current(get_included_files()));

            // check if file exist relativ to index file
            if (file_exists($indexFilePath . $filePath)) {

                // get timestamp based on this relativ path
                $mtime = filemtime($indexFilePath . $filePath);

                // write generated timestamp to path
                // but use old path not the relativ one
                return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
            } else {

                return $filePath;
            }
        }
    }

}

Şerefe ve teşekkürler.


7

Komut dosyası düğümü (veya css) öğesini dinamik olarak oluşturan istemci taraflı DOM yaklaşımını bulamadınız:

<script>
    var node = document.createElement("script"); 
    node.type = "text/javascript";
    node.src = 'test.js?'+Math.floor(Math.random()*999999999);
    document.getElementsByTagName("head")[0].appendChild(node);
</script>

6

krom vardır google Sert yükle yanı sıra Önbelleği Boşalt ve Tam Yeniden Yükle birini seçmek için (In Modu kontrol) tıklayın ve yükle düğmesini tutabilir option.You.


Bunlar, F12 aka "Dev Araçlar" aka ctrl + shift + i, nam kastediyoruz "Modu kontrol" tarafından, netleştirmek için ant menu> More Tools> Developer Tools, nam right click> Inspect Element. Ayrıca her yerde yeniden yükleme zor yeniden yüklemek için dev araçları (yeri unuttum) bir yere gömülü bir ayar var.
Jonny Asmar

5

Oturum kimliğini js / css dosyasının spureous parametresi olarak eklerseniz "oturum genelinde önbelleğe almayı" zorlayabilirsiniz:

<link rel="stylesheet" src="myStyles.css?ABCDEF12345sessionID" />
<script language="javascript" src="myCode.js?ABCDEF12345sessionID"></script>

Sürüm genelinde bir önbellekleme istiyorsanız, dosya tarihini veya benzerini yazdırmak için bazı kodlar ekleyebilirsiniz. Java kullanıyorsanız, bağlantıyı zarif bir şekilde oluşturmak için özel bir etiket kullanabilirsiniz.

<link rel="stylesheet" src="myStyles.css?20080922_1020" />
<script language="javascript" src="myCode.js?20080922_1120"></script>

5

Diyelim ki şu adreste bir dosyanız var:

/styles/screen.css

URI'ye sürüm bilgileri içeren bir sorgu parametresi ekleyebilirsiniz, örn:

/styles/screen.css?v=1234

veya sürüm bilgilerinin önüne başlayabilirsiniz, örneğin:

/v/1234/styles/screen.css

Onlar bir belirtirseniz o hangi vasıta göreli URL'ler kullanarak resimlere atıfta çünkü IMHO İkinci yöntem CSS dosyaları için iyidir background-imageşöyle:

body {
    background-image: url('images/happy.gif');
}

URL'si etkili olacak:

/v/1234/styles/images/happy.gif

Bu, kullanılan sürüm numarasını güncellerseniz sunucunun bunu yeni bir kaynak olarak ele alacağı ve önbelleğe alınmış bir sürümü kullanamayacağı anlamına gelir. Sürüm numaranızı Subversion / CVS / etc'ye dayandırırsanız. revizyon, CSS dosyalarında referans alınan görüntülerde yapılan değişikliklerin fark edileceği anlamına gelir. İlk şemada, yani URL images/happy.gifile/styles/screen.css?v=1235 DİR/styles/images/happy.gif herhangi bir sürüm bilgisi içermiyor.

Java sunucu uygulamaları ile bu tekniği kullanarak bir önbellekleme çözümü uyguladım ve sadece /v/*temel kaynağa (yani /styles/screen.css) delege olan bir sunucu uygulaması ile istekleri işlemek . Geliştirme modunda ben (eğer Tomcat en devredebilir eğer bu tipik bir 304 sonuçlanır sunucu ile kaynağın tazeliğini kontrol daima müşteri anlatmak başlıkları önbelleğe seti DefaultServletve .css, .jsise dağıtım modunda, vb dosya değişmedi) "Sonsuza kadar önbellek" diyen başlıkları ayarladım.


Yalnızca göreli URL'ler kullanıyorsanız, gerektiğinde yeniden adlandırabileceğiniz bir klasör eklemek işe yarayacaktır. Ve sonra temel klasörden, yani PHP: uygun klasöre yönlendirdiğinizden emin olun <?php header( 'Location: folder1/login.phtml' ); ?>.
Gruber

1
İkinci yöntemi kullanarak, bir CSS değişikliği, göreli URL'lerle referans verilen tüm görüntülerin önbelleğe alınmış kopyalarını geçersiz kılabilir ve bu istenebilir veya istenmeyebilir.
TomG

5

CSS / JS URL'si gibi rastgele bir sayı ekleyebilirsiniz.

example.css?randomNo=Math.random()

5

ASP.NET için gelişmiş seçeneklerle (hata ayıklama / bırakma modu, sürümler) sonraki çözümü varsayalım:

Js veya Css dosyaları bu şekilde dahil edilmiştir:

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

Global.JsPostfix ve Global.CssPostfix, Global.asax içinde şu şekilde hesaplanır:

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();
    }
    ...
}

4

Son zamanlarda bunu Python kullanarak çözdüm. Burada kod (diğer dillere uyarlanması kolay olmalıdır):

def import_tag(pattern, name, **kw):
    if name[0] == "/":
        name = name[1:]
    # Additional HTML attributes
    attrs = ' '.join(['%s="%s"' % item for item in kw.items()])
    try:
        # Get the files modification time
        mtime = os.stat(os.path.join('/documentroot', name)).st_mtime
        include = "%s?%d" % (name, mtime)
        # this is the same as sprintf(pattern, attrs, include) in other
        # languages
        return pattern % (attrs, include)
    except:
        # In case of error return the include without the added query
        # parameter.
        return pattern % (attrs, name)

def script(name, **kw):
    return import_tag("""<script type="text/javascript" """ +\
        """ %s src="/%s"></script>""", name, **kw)

def stylesheet(name, **kw):
    return import_tag('<link rel="stylesheet" type="text/css" ' +\
        """%s href="/%s">', name, **kw) 

Bu kod temelde dosyaların zaman damgasını URL'ye bir sorgu parametresi olarak ekler. Aşağıdaki fonksiyonun çağrısı

script("/main.css")

sonuçlanacak

<link rel="stylesheet" type="text/css"  href="/main.css?1221842734">

Elbette avantajı, html'nizi bir daha asla değiştirmek zorunda kalmamanızdır, CSS dosyasına dokunmak otomatik olarak önbellek geçersizliğini tetikleyecektir. Çok iyi çalışır ve tepegöz fark edilmez.


os.stat () bir darboğaz oluşturabilir mi?
hoju

@Richard stat, disk çok yavaş ve istek çok fazla ise bir darboğaz olabilir. Bu durumda, zaman damgasını bellekte bir yerde önbelleğe alabilir ve bu önbelleği her yeni dağıtımda temizleyebilirsiniz. Yine de bu karmaşıklık, kullanım durumlarının çoğunda gerekli olmayacaktır.
pi.

4

Git + PHP kullanıyorsanız, git repo'sında her değişiklik yapıldığında aşağıdaki kodu kullanarak komut dosyasını önbellekten yeniden yükleyebilirsiniz:

exec('git rev-parse --verify HEAD 2> /dev/null', $gitLog);
echo '  <script src="/path/to/script.js"?v='.$gitLog[0].'></script>'.PHP_EOL;

4

Önbelleğe almayı önlemek isteyen bir geliştiriciyseniz, krom ağı sekmesinde önbellek devre dışı bırakma seçeneği vardır. Aksi takdirde, bunu iki komut dosyası etiketi kullanarak bir sunucu oluşturma çerçevesi olmadan yapabilirsiniz.

<script type="text/javascript">
    document.write('<script type="text/javascript" src="myfile.js?q=' + Date.now() + '">
    // can't use myfile.js stuff yet
</script>')
<script type="text/javascript">
    // do something with myfile.js
</script>

4

Bu soru çok eski ve kimse bu sorunu googles ilk şey görünür. Bu, op'un istediği soruya bir cevap değildir, bunun yerine geliştirme ve test sırasında bu problemle geliştiricilere bir cevaptır. Ve yinelenen olarak işaretleneceğinden bu konuya yeni bir soru gönderemiyorum.

Diğerleri gibi ben de kısa bir süre önbelleği kaldırmak istedim.

"keep caching consistent with the file" .. çok fazla güçlük çekiyor ..

Genel olarak konuşursak, daha fazla yüklemeyi umursamıyorum - çoğu projede değişmeyen dosyaları yeniden yüklemek bile pratik olarak önemsizdir. Bir uygulama geliştirirken - çoğunlukla diskten yüklüyoruz localhost:port - bu yüzden bu increase in network trafficsorun bir anlaşma kırma sorunu değil .

Çoğu küçük proje sadece oyun oynamaktadır - asla üretime son vermezler. yani onlar için başka bir şeye ihtiyacınız yok ..

Kullanmak Böyle Sanki Chrome Dev Araçlar , Aşağıdaki resimde gibi bu devre dışı önbelleğe alma yaklaşımı takip edebilirsiniz: önbelleğe alınmış dosyaları yeniden yüklemeye krom nasıl zorlanır

Ve eğer varsa firefox önbelleğe alma sorunlarını: firefox'ta varlık yeniden yüklemeye zorlama

geliştirme sırasında Firefox'ta önbellekleme nasıl devre dışı bırakılır Bunu yalnızca geliştirme aşamasında yapın, ayrıca üretim için yeniden yüklemeyi zorlamak için bir mekanizmaya da ihtiyacınız vardır, çünkü kullanıcılarınız uygulamanızı sık sık güncellerseniz ve yanıtlarda açıklananlar gibi özel bir önbellek senkronizasyon mekanizması sağlamazsanız eski önbellek geçersiz kılınmış modülleri kullanacaktır yukarıda.

Evet, bu bilgi zaten önceki cevaplarda ama yine de bulmak için bir google arama yapmak gerekiyordu.

Umarım bu cevap çok açıktır ve şimdi gerek yok.


OP bir şey sordu ve başka bir şey yanıtladı. Yerel ancak üretimde kuvvet yükü ile ilgili değil ve devre dışı önbellek vs. yukarıdaki takip etmek son kullanıcılara soramazsın
Jitendra Pancholi

3

Buradaki tüm cevaplar, adlandırma şemasında, olumsuz yanları olan bir çeşit versiyonlama önermektedir.

Tarayıcılar, neyin önbelleğe alınacağının ve web sunucusu yanıtını, özellikle http başlıklarını okuyarak önbelleğe alınmamasının farkında olmalıdır - bu kaynak ne kadar süreyle geçerlidir? Bu kaynak en son aldığımdan beri güncellendi mi? ve benzeri.

İşler 'doğru' yapılandırılırsa, uygulamanızın dosyalarının güncellenmesi (bir noktada) tarayıcı önbelleklerini yenilemelidir. Örneğin, web sunucunuzu tarayıcıya asla dosyaları önbelleğe almamasını söyleyecek şekilde yapılandırabilirsiniz (bu kötü bir fikirdir).

Bunun nasıl çalıştığına dair daha ayrıntılı bir açıklama burada https://www.mnot.net/cache_docs/#WORK


3

Sabit yeniden yükleme yapmak istediğiniz yere bu kodu ekleyin (tarayıcıyı önbelleğe alınmış CSS / JS dosyalarını yeniden yüklemeye zorlayın) .load içinde bunu yapın, böylece bir döngü gibi yenilenmez

 $( window ).load(function() {
   location.reload(true);
});

Chrome'da çalışmıyor. Disk önbelleğinden hala öğeler yükleniyor
Jason Kim

3

Dosyanın tarihini eklemek için sunucu tarafı kodunu kullanmanız yeterlidir ... bu şekilde önbelleğe alınır ve yalnızca dosya değiştiğinde yeniden yüklenir

ASP.NET'te

<link rel="stylesheet" href="~/css/custom.css?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/css/custom.css")).ToString(),"[^0-9]", ""))" />

<script type="text/javascript" src="~/js/custom.js?d=@(System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/js/custom.js")).ToString(),"[^0-9]", ""))"></script>    

Bu basitleştirilebilir:

<script src="<%= Page.ResolveClientUrlUnique("~/js/custom.js") %>" type="text/javascript"></script>

Sayfa'yı genişletmek için projenize bir uzantı yöntemi ekleyerek:

public static class Extension_Methods
{
    public static string ResolveClientUrlUnique(this System.Web.UI.Page oPg, string sRelPath)
    {
        string sFilePath = oPg.Server.MapPath(sRelPath);
        string sLastDate = System.IO.File.GetLastWriteTime(sFilePath).ToString();
        string sDateHashed = System.Text.RegularExpressions.Regex.Replace(sLastDate, "[^0-9]", "");

        return oPg.ResolveClientUrl(sRelPath) + "?d=" + sDateHashed;
    }
}

2

Aşağıdaki süreci uygulamanızı öneririm:

  • css / js dosyalarınızı her dağıttığınızda sürüm olarak güncelleyin: screen.1233.css (bir sürüm sistemi kullanıyorsanız sayı SVN revizyonunuz olabilir)

  • yükleme sürelerini optimize etmek için onları küçültün

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.