代码之家  ›  专栏  ›  技术社区  ›  Michael Edwards

强制刷新缓存的CSS数据

  •  37
  • Michael Edwards  · 技术社区  · 14 年前

    是否可能强制浏览器刷新缓存的CSS?

    这并不像每个请求那么简单。我们有一个网站已经稳定了一段时间的CSS。

    现在我们需要对CSS进行一些主要的更新;但是,缓存了CSS的浏览器在几天内不会收到新的CSS,从而导致呈现问题。

    有没有办法强制刷新CSS,还是我们最好选择特定于版本的CSS URL?

    4 回复  |  直到 5 年前
        1
  •  53
  •   Tim M.    5 年前

    有几个问题需要考虑,并且有多种方法可以解决这个问题。第一, the spec

    我们要完成什么?

    理想情况下,修改后的资源将在第一次被请求时无条件地获取,然后从本地缓存中检索,直到其到期,并且没有后续的服务器交互。

    观察到的缓存行为

    跟踪不同排列可能会有点混乱,所以我创建了下表。这些观察结果是通过从chrome向IIS发出请求并在开发人员控制台中观察响应/行为生成的。

    在所有情况下,新的URL都将导致HTTP 200。重要的是发生了什么 后来的 请求。

    +---------------------+--------------------+-------------------------+
    |        Type         |   Cache Headers    |     Observed Result     |
    +---------------------+--------------------+-------------------------+
    | Static filename     | Expiration +1 Year | Taken from cache        |
    | Static filename     | Expire immediately | Never caches            |
    | Static filename     | None               | HTTP 304 (not modified) |
    |                     |                    |                         |
    | Static query string | Expiration +1 Year | HTTP 304 (not modified) |
    | Static query string | Expire immediately | HTTP 304 (not modified) |
    | Static query string | None               | HTTP 304 (not modified) |
    |                     |                    |                         |
    | Random query string | Expiration +1 Year | Never caches            |
    | Random query string | Expire immediately | Never caches            |
    | Random query string | None               | Never caches            |
    +---------------------+--------------------+-------------------------+
    

    然而 请记住,浏览器和Web服务器的行为并不总是如我们所期望的那样。一个著名的例子: in 2012 mobile Safari began caching POST requests . 开发人员不高兴。

    查询字符串

    ASP.NET MVC Razor语法中的示例,但几乎适用于任何服务器处理语言。

    …因为有些应用程序传统上使用GET和HEAD 查询URL(包含“?”的URL)在rel-path部分)执行 有明显副作用的手术,不能治疗 除非服务器提供了一个显式的 到期时间。这意味着来自HTTP/1.0的响应 此类URI的服务器不应从缓存中获取。

    在HTML中包含的CSS URL的末尾附加一个随机参数将强制执行一个新的请求,并且服务器应该使用HTTP 200(不是304,即使它还没有 改性)。

    <link href="normalfile.css?random=@Environment.TickCount" />
    

    当然,如果我们随机化查询字符串 每一个 请求,这将完全击败缓存。 对于生产应用程序来说,这是很少/永远不可取的。

    如果只维护几个URL,则可以手动修改它们以包含内部版本号或日期:

    @{
        var assembly = Assembly.GetEntryAssembly();
        var name = assembly.GetName();
        var version = name.Version;
    }
    
    <link href="normalfile.css?build=@version.MinorRevision" />
    

    这将在用户代理第一次遇到URL时引起一个新的请求,但随后的请求大多会返回304s。这仍然会引起一个请求,但至少整个文件没有被服务。

    路径修改

    更好的解决方案是创建新路径。只要稍加努力,这个过程就可以自动地用版本号(或其他一致的标识符)重写路径。

    This answer 为非Microsoft平台显示一些简单而优雅的选项。

    微软开发人员可以使用一个HTTP模块来截取给定文件类型的所有请求,或者利用MVC路由/控制器组合来提供正确的文件(我还没有看到这样做,但我相信这是可行的)。

    当然,最简单(不一定是最快或最好)的方法就是在每个版本中重命名有问题的文件,并引用 link 标签。

    TLDR

    • 更改文件名或查询字符串
    • 使用每次发布只发生一次的更改
    • 文件重命名优于查询字符串更改
    • 始终设置HTTP头以最大化缓存的好处
        2
  •  7
  •   Andy Gee    12 年前

    我认为重命名CSS文件是一个更好的主意。它可能不适合所有应用程序,但它将确保用户只需加载一次CSS文件。在末尾添加一个随机字符串可以确保他们每次都要下载它。 上面的javascript方法和apache方法也是如此。 有时候简单的答案可能是最有效的。

    另一个解决方案是:

    <FilesMatch "\.(js|css)$">
        Header set Cache-Control "max-age=86400, public"
    </FilesMatch>
    

    这将最大缓存使用时间限制为1天或86400秒。

        3
  •  0
  •   patmortech    12 年前

    你也许能用阿帕奇语来做…

    <FilesMatch "\.(html|htm|js|css)$">
    FileETag None
    <IfModule mod_headers.c>
    Header unset ETag
    Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
    </IfModule>
    </FilesMatch>
    
        4
  •  0
  •   RobDigital    5 年前

    请先阅读蒂姆·梅多拉的回答,因为这是一篇非常有见识、非常努力的文章。

    现在我将告诉您如何使用PHP。我不想为传统的版本控制而烦恼,也不想试图维护1000多个页面,但我想确保用户总是能得到我的CSS的最新版本并缓存它。

    所以我使用查询字符串技术和PHP filemtime() 它将返回上次修改的时间戳。

    此函数返回文件的数据块被写入的时间,即文件内容被更改的时间。

    在我的webapps中,我使用config.php文件来存储我的设置,因此在这里我将生成如下的变量:

    $siteCSS = "/css/standard.css?" .filemtime($_SERVER['DOCUMENT_ROOT']. "/css/standard.css");
    

    然后在我的所有页面中,我都会像这样引用我的CSS:

    <link rel="stylesheet" type="text/css" media="all" href="<?php echo $siteCSS?>" />
    

    到目前为止,在PHP/IIS上,这对我来说非常有用。