关于缓存:强制刷新缓存的CSS数据

Force refresh of cached CSS data

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

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

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

有没有办法强制刷新CSS或者我们最好只选择版本特定的CSS URL?


有几件事需要考虑,有多种方法可以解决这个问题。一,规格

我们想要完成什么?

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

观察到的缓存行为

跟踪不同的排列可能有点令人困惑,所以我创建了下表。这些观察是通过向Chrome发出针对IIS的请求并在开发人员控制台中观察响应/行为而生成的。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+---------------------+--------------------+-------------------------+
|        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服务器并不总是按照我们期望的方式运行。一个着名的例子:2012年,移动Safari开始缓存POST请求。开发人员并不高兴。

请求参数

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

...since some applications have traditionally used GETs and HEADs with
query URLs (those containing a"?" in the rel_path part) to perform
operations with significant side effects, caches MUST NOT treat
responses to such URIs as fresh unless the server provides an explicit
expiration time. This specifically means that responses from HTTP/1.0
servers for such URIs SHOULD NOT be taken from a cache.

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

1
<link href="[email protected]" />

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

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

1
2
3
4
5
6
7
@{
    var assembly = Assembly.GetEntryAssembly();
    var name = assembly.GetName();
    var version = name.Version;
}

<link href="[email protected]" />

这将在用户代理第一次遇到URL时产生新请求,但后续请求将主要返回304。这仍然会导致请求,但至少不提供整个文件。

路径修改

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

这个答案显示了非Microsoft平台的一些简单而优雅的选项。

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

当然,最简单的(不一定是最快或最好的)方法是仅使用每个版本重命名相关文件,并引用link标记中的更新路径。

TLDR

  • 更改文件名或查询字符串
  • 使用每个版本仅发生一次的更改
  • 文件重命名优于查询字符串更改
  • 始终设置HTTP标头以最大化缓存的好处


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

另一种解决方案是

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

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


请先阅读Tim Medora的回答,因为这是一篇非常有见识且努力的帖子。

现在我将告诉你我是如何用PHP做的。我不想打扰传统版本或试图维护1000多个页面,但我想确保用户始终获取我的CSS的最新版本并缓存它。

所以我使用查询字符串技术和PHP filemtime()来返回最后修改的时间戳。

This function returns the time when the data blocks of a file were being written to, that is, the time when the content of the file was changed.

在我的webapps中,我使用config.php文件来存储我的设置,所以在这里我将创建一个这样的变量:

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

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

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

到目前为止,这对我来说非常适合PHP / IIS。


Yu也许能够在apache中做到这一点......

1
2
3
4
5
6
7
8
9
<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>