簡體   English   中英

強制瀏覽器清除緩存

[英]Force browser to clear cache

有沒有一種方法可以在我的頁面上放置一些代碼,以便當有人訪問網站時,它會清除瀏覽器緩存,以便他們可以查看更改?

使用的語言:ASP.NET、VB.NET,當然還有 HTML、CSS 和 jQuery。

如果這是關於.css.js更改,一種方法是“緩存破壞”是通過在每個版本的文件名后附加類似“ _versionNo ”的內容。 例如:

script_1.0.css // This is the URL for release 1.0
script_1.1.css // This is the URL for release 1.1
script_1.2.css // etc.

或者在文件名之后執行:

script.css?v=1.0 // This is the URL for release 1.0
script.css?v=1.1 // This is the URL for release 1.1
script.css?v=1.2 // etc.

您可以查看此鏈接以了解它是如何工作的。

查看緩存控制過期META 標記。

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="Mon, 22 Jul 2002 11:12:01 GMT">

另一種常見做法是將不斷變化的字符串附加到請求文件的末尾。 例如:

<script type="text/javascript" src="main.js?v=12392823"></script>

2012 年更新

這是一個老問題,但我認為它需要一個更新的答案,因為現在有一種方法可以更好地控制網站緩存。

離線 Web 應用程序(實際上是任何 HTML5 網站)中, applicationCache.swapCache()可用於更新網站的緩存版本,而無需手動重新加載頁面。

這是在 HTML5 Rocks 上使用應用程序緩存初學者指南中的代碼示例,解釋了如何將用戶更新到您網站的最新版本:

// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {

  window.applicationCache.addEventListener('updateready', function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
      // Browser downloaded a new app cache.
      // Swap it in and reload the page to get the new hotness.
      window.applicationCache.swapCache();
      if (confirm('A new version of this site is available. Load it?')) {
        window.location.reload();
      }
    } else {
      // Manifest didn't changed. Nothing new to server.
    }
  }, false);

}, false);

另請參閱在 Mozilla 開發人員網絡上使用應用程序緩存以獲取更多信息。

2016 年更新

Web 上的事情變化很快。 這個問題是在 2009 年提出的,2012 年我發布了關於處理問題中描述的問題的新方法的更新。 又過了 4 年,現在它似乎已經被棄用了。 感謝cgaldiolo在評論中指出。

目前,截至 2016 年 7 月, HTML 標准第 7.9 節,離線 Web 應用程序包含棄用警告:

此功能正在從 Web 平台中刪除。 (這是一個需要很多年的漫長過程。)此時強烈建議不要使用任何離線 Web 應用程序功能。 改用服務工作者。

我在 2012 年提到的使用Mozilla Developer Network 上的應用程序緩存也是如此:

已棄用
此功能已從 Web 標准中刪除。 雖然一些瀏覽器可能仍然支持它,但它正在被刪除。 不要在舊項目或新項目中使用它。 使用它的頁面或 Web 應用程序可能隨時中斷。

另請參閱錯誤 1204581 - 如果啟用了 Service Worker fetch 攔截,則為 AppCache 添加棄用通知

不是這樣。 一種方法是在傳遞內容時發送適當的標頭以強制瀏覽器重新加載:

確保所有瀏覽器都沒有緩存網頁。

如果您在 SO 上搜索"cache header"或類似內容,您將找到 ASP.NET 特定示例。

如果您無法控制服務器端的標頭,另一種不太干凈但有時唯一的方法是向正在調用的資源添加一個隨機的 GET 參數:

myimage.gif?random=1923849839

對於靜態資源,正確緩存將使用具有每個部署或文件版本值的查詢參數 這將具有在每次部署后清除緩存的效果。

/Content/css/Site.css?version={FileVersionNumber}

這是 ASP.NET MVC 示例。

<link href="@Url.Content("~/Content/Css/Reset.css")?version=@this.GetType().Assembly.GetName().Version" rel="stylesheet" type="text/css" />

不要忘記更新程序集版本。

我遇到了類似的問題,這就是我解決它的方法:

  1. index.html文件中,我添加了清單:

     <html manifest="cache.manifest">
  2. <head>部分包含更新緩存的腳本:

     <script type="text/javascript" src="update_cache.js"></script>
  3. <body>部分中,我插入了 onload 函數:

     <body onload="checkForUpdate()">
  4. cache.manifest我已經放置了所有要緩存的文件。 現在很重要的是,它在我的情況下(Apache)只需在每次“版本”注釋時更新即可。 也可以選擇使用“?ver=001”或名稱末尾的內容命名文件,但不需要 僅更改# version 1.01會觸發緩存更新事件。

     CACHE MANIFEST # version 1.01 style.css imgs/logo.png #all other files

    在 index.html 中包含 1.、2. 和 3. 點很重要。 除此以外

    GET http://foo.bar/resource.ext net::ERR_FAILED

    發生的原因是每個“子”文件都在頁面已經緩存時嘗試緩存頁面。

  5. update_cache.js文件中,我放置了以下代碼:

     function checkForUpdate() { if (window.applicationCache != undefined && window.applicationCache != null) { window.applicationCache.addEventListener('updateready', updateApplication); } } function updateApplication(event) { if (window.applicationCache.status != 4) return; window.applicationCache.removeEventListener('updateready', updateApplication); window.applicationCache.swapCache(); window.location.reload(); }

現在您只需更改文件,並且在清單中您必須更新版本注釋。 現在訪問 index.html 頁面將更新緩存。

解決方案的部分不是我的,但我通過互聯網找到了它們並將它們放在一起以使其有效。

我有一個案例,我會在網上為客戶拍照,如果照片更改,則需要更新 div。 瀏覽器仍然顯示舊照片。 所以我使用了調用隨機 GET 變量的技巧,它每次都是唯一的。 這是如果它可以幫助任何人

<img src="/photos/userid_73.jpg?random=<?php echo rand() ?>" ...

編輯正如其他人所指出的,以下是更有效的解決方案,因為它只會在更改圖像時重新加載圖像,並通過文件大小識別此更改:

<img src="/photos/userid_73.jpg?modified=<? filemtime("/photos/userid_73.jpg")?>"

很多答案都沒有抓住重點 - 大多數開發人員都清楚關閉緩存效率低下。 但是,在許多常見情況下,效率並不重要並且默認緩存行為被嚴重破壞。

其中包括嵌套的、迭代的腳本測試(最大的一個!)和損壞的第三方軟件解決方法。 此處給出的解決方案均不足以解決此類常見情況。 大多數 Web 瀏覽器的緩存過於激進,並且沒有提供避免這些問題的合理方法。

將 URL 更新為以下內容對我有用:

/custom.js?id=1

通過在?id=之后添加一個唯一編號並為新更改增加它,用戶不必按CTRL + F5來刷新緩存。 或者,您可以在?id=之后附加當前時間或紀元的哈希或字符串版本

類似於?id=1520606295

<meta http-equiv="pragma" content="no-cache" />

另請參閱https://stackoverflow.com/questions/126772/how-to-force-a-web-browser-not-to-cache-images

是有關在 ASP.NET 中設置緩存的 MDSN 頁面。

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(False)
Response.Cache.VaryByParams("Category") = True

If Response.Cache.VaryByParams("Category") Then
   '...
End If

我實現了這個對我有用的簡單解決方案(尚未在生產環境中使用):

function verificarNovaVersio() {
    var sVersio = localStorage['gcf_versio'+ location.pathname] || 'v00.0.0000';
    $.ajax({
        url: "./versio.txt"
        , dataType: 'text'
        , cache: false
        , contentType: false
        , processData: false
        , type: 'post'
     }).done(function(sVersioFitxer) {
        console.log('Versió App: '+ sVersioFitxer +', Versió Caché: '+ sVersio);
        if (sVersio < (sVersioFitxer || 'v00.0.0000')) {
            localStorage['gcf_versio'+ location.pathname] = sVersioFitxer;
            location.reload(true);
        }
    });
}

我有一個小文件位於 html 所在的位置:

“版本.txt”:

v00.5.0014

這個函數在我所有的頁面中都會被調用,所以在加載它時會檢查 localStorage 的版本值是否低於當前版本並執行

location.reload(true);

...強制從服務器而不是從緩存重新加載。

(顯然,您可以使用 cookie 或其他持久性客戶端存儲代替 localStorage)

我選擇這個解決方案是因為它的簡單性,因為只有維護一個文件“versio.txt”才會強制重新加載整個站點。

queryString 方法很難實現,而且也會被緩存(如果你從 v1.1 改到以前的版本會從緩存中加載,那么這意味着緩存沒有被刷新,所有以前的版本都在緩存中)。

我是一個小新手,我非常感謝您的專業檢查和審查,以確保我的方法是一種很好的方法。

希望能幫助到你。

不確定這是否真的對您有幫助,但這就是緩存在任何瀏覽器上的工作方式。 當瀏覽器請求文件時,它應該總是向服務器發送請求,除非有“離線”模式。 服務器將讀取一些參數,如修改日期或 etags。

服務器將為 NOT MODIFIED 返回 304 錯誤響應,瀏覽器將不得不使用其緩存。 如果 etag 在服務器端未驗證或修改日期低於當前修改日期,則服務器應返回帶有新修改日期或 etags 或兩者的新內容。

如果沒有緩存數據發送到瀏覽器,我想行為是不確定的,瀏覽器可能會或可能不會緩存不告訴它們是如何緩存的文件。 如果您在響應中設置緩存參數,它將正確緩存您的文件,然后服務器可能會選擇返回 304 錯誤或新內容。

這是應該如何做的。 在 url 中使用隨機參數或版本號更像是一種黑客攻擊。

http://www.checkupdown.com/status/E304.html http://en.wikipedia.org/wiki/HTTP_ETag http://www.xpertdeveloper.com/2011/03/last-modified-header-vs- expire-header-vs-etag/

閱讀后我看到還有一個過期日期。 如果您有問題,可能是您設置了到期日期。 換句話說,當瀏覽器緩存您的文件時,因為它有一個到期日期,它不應該在該日期之前再次請求它。 換句話說,它永遠不會向服務器詢問文件,也永遠不會收到未修改的 304。 它只會使用緩存,直到到期日期或緩存被清除。

所以這是我的猜測,你有某種到期日期,你應該使用最后修改的 etags 或所有這些的混合,並確保沒有到期日期。

如果人們傾向於經常刷新並且文件沒有被大量更改,那么設置一個大的到期日期可能是明智的。

我的2美分!

除了設置 Cache-control: no-cache 之外,如果您希望每次都刷新本地副本,您還應該將 Expires 標頭設置為 -1(某些版本的 IE 似乎需要這樣做)。

請參閱HTTP 緩存 - 檢查服務器,始終發送 If-Modified-Since

有一個技巧可以使用。技巧是在腳本標記中的文件名后附加一個參數/字符串,並在文件更改時更改它。

<script src="myfile.js?version=1.0.0"></script>

瀏覽器將整個字符串解釋為文件路徑,即使在“?”之后是什么。 是參數。 所以現在發生的是,下次更新文件時,只需更改網站上腳本標記中的數字(例如<script src="myfile.js?version=1.0.1"></script> )和每個用戶瀏覽器將看到文件已更改並獲取新副本。

強制瀏覽器清除緩存或重新加載正確的數據? 我已經嘗試了 stackoverflow 中描述的大多數解決方案,有些工作,但過了一會兒,它最終會緩存並顯示以前加載的腳本或文件。 有沒有另一種方法可以清除緩存(css、js 等)並實際適用於所有瀏覽器?

到目前為止,我發現如果您更改服務器上文件的日期和時間,可以單獨重新加載特定資源。 “清除緩存”並不像它應該的那么容易。 我沒有清除瀏覽器上的緩存,而是意識到“觸摸”緩存的服務器文件實際上會更改緩存在服務器上的源文件的日期和時間(在 Edge、Chrome 和 Firefox 上測試)並且大多數瀏覽器會自動下載最多的您服務器上最新內容的最新副本(代碼、圖形以及任何多媒體)。 我建議您在程序運行之前復制服務器上最新的腳本並“做觸摸事情”解決方案,這樣它就會將所有問題文件的日期更改為最新的日期和時間,然后下載一個新的副本到您的瀏覽器:

<?php
   touch('/www/sample/file1.css');
   touch('/www/sample/file2.js');
?>

然后......你程序的其余部分......

我花了一些時間來解決這個問題(因為許多瀏覽器對不同命令的行為不同,但它們都檢查文件的時間並與瀏覽器中下載的副本進行比較,如果不同的日期和時間,將進行刷新),如果您不能走正確的道路,總有另一種可用且更好的解決方案。 最好的問候和快樂的露營。 順便說一下 touch(); 或替代方案適用於許多編程語言,包括 javascript bash sh php,您可以在 html 中包含或調用它們。

如果您是 Wordpress 開發人員,我有一些好消息要告訴您。

只需搜索、安裝並激活名為:reBusted 的 Wordpress 插件。

無需配置。

如果內容已更新,它將自動強制刷新緩存,並完全可靠地解決此問題。 在數百個客戶 Wordpress 網站上測試和使用 - 在任何地方都可以完美運行。

不能推薦它。

如果您使用 Wordpress,這是迄今為止您最好的選擇和最優雅的解決方案。

享受!

對於 webpack 用戶:-

我在我的 webpack 配置中添加了 chunkhash 時間。 這解決了我在每次部署時使緩存無效的問題。 此外,我們需要注意 index.html/asset.manifest 不會緩存在您的 CDN 或瀏覽器中。 webpack 配置中塊名稱的配置將如下所示:-

文件名:[chunkhash]-${Date.now()}.js

或者如果您使用的是 contenthash 那么

文件名:[contenthash]-${Date.now()}.js

這是我在我的一個應用程序中使用 PHP 解決的簡單解決方案。

所有 JS 和 CSS 文件都放在一個帶有版本名稱的文件夾中。 示例:“1.0.01”

root\1.0.01\JS
root\1.0.01\CSS

創建了一個 Helper 並在那里定義了版本號

<?php
function system_version()
{
    return '1.0.07';
}

並鏈接 JS 和 SCC 文件,如下所示

<script src="<?= base_url(); ?>/<?= system_version();?>/js/generators.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="<?= base_url(); ?>/<?= system_version(); ?>/css/view-checklist.css" />

每當我對任何 JS 或 CSS 文件進行更改時,我都會更改 Helper 中的系統版本並重命名文件夾並部署它。

我遇到了同樣的問題,我所做的只是更改鏈接到我的 index.html 文件的文件名,然后進入 index.html 文件並更新它們的名稱,這不是最佳做法,但如果它有效,它就會起作用。 瀏覽器將它們視為新文件,因此它們會重新下載到用戶設備上。

示例:我想更新一個 css 文件,其名稱為 styles.css,將其更改為 styless.css

Go 到 index.html 並更新,並將其更改為

如果有興趣,我已經找到了在 .NET MVC (.net fw 4.8) 的上下文中讓瀏覽器刷新的解決方案。css 和 .js 以及捆綁包的使用。 我想讓瀏覽器僅在部署新程序集后才刷新緩存文件。

根據 Paulius Zaliaduonis 的回應,我的解決方案如下:

  1. 將您的應用程序基礎 url 存儲在 web 配置應用程序設置中(HttpContext 在 RegisterBundle 運行時尚不可用...),然后根據 xml 的配置(調試,暫存,發布...)更改此參數轉換
  2. 在 BundleConfig RegisterBundles 中通過反射的方式獲取程序集版本,並...
  3. ...更改 styles 和腳本的默認標記格式,以便捆綁系統生成鏈接和腳本標記,並在其上附加查詢字符串參數。

這是代碼

public static void RegisterBundles(BundleCollection bundles)
{
   string baseUrl = system.Configuration.ConfigurationManager.AppSettings["by.app.base.url"].ToString();
       
   string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
   
   Styles.DefaultTagFormat = $"<link href='{baseUrl}{{0}}?v={assemblyVersion}' rel='stylesheet'/>";
   Scripts.DefaultTagFormat = $"<script src='{baseUrl}{{0}}?v={assemblyVersion}'></script>";
}

你會得到像這樣的標簽

<script src="https://example.org/myscriptfilepath/script.js?v={myassemblyversion}"></script>

您只需要記住在部署之前構建一個新版本。

再見

您是要清除緩存,還是只是確保您當前(已更改?)的頁面沒有被緩存?

如果是后者,應該很簡單

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM