强制刷新缓存的 CSS 数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3870726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force refresh of cached CSS data
提问by Michael Edwards
Is it possible force the browser to fresh the cached CSS?
是否可以强制浏览器刷新缓存的 CSS?
This is not as simple as every request. We have a site that has had stable CSS for a while.
这不像每个请求那么简单。我们有一个具有稳定 CSS 的站点。
Now we need to make some major updates to the CSS; however, browsers that have cached the CSS will not receive the new CSS for a couple of days causing rendering issues.
现在我们需要对 CSS 进行一些重大更新;但是,缓存了 CSS 的浏览器在几天内不会收到新的 CSS,从而导致呈现问题。
Is there a way to force refresh of the CSS or are we better just opting for version specific CSS URLs?
有没有办法强制刷新 CSS 还是我们最好只选择特定于版本的 CSS URL?
回答by Tim Medora
There are several things to consider and a variety of ways to approach this. First, the spec
有几件事需要考虑,也有多种方法可以解决这个问题。一、规格
What are we trying to accomplish?
我们试图完成什么?
Ideally, a modified resource will be unconditionally fetched the first time it is requested, and then retrieved from a local cache until it expires with no subsequent server interaction.
理想情况下,修改后的资源将在第一次被请求时无条件地获取,然后从本地缓存中检索,直到它在没有后续服务器交互的情况下过期。
Observed Caching Behavior
观察到的缓存行为
Keeping track of the different permutations can be a bit confusing, so I created the following table. These observations were generated by making requests from Chrome against IIS and observing the response/behavior in the developer console.
跟踪不同的排列可能有点令人困惑,因此我创建了下表。这些观察结果是通过从 Chrome 向 IIS 发出请求并观察开发者控制台中的响应/行为而生成的。
In all cases, a new URL will result in HTTP 200. The important thing is what happens with subsequentrequests.
在所有情况下,新 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 |
+---------------------+--------------------+-------------------------+
However, remember that browsers and web servers don't always behave the way we expect. A famous example: in 2012 mobile Safari began caching POST requests. Developers weren't pleased.
但是,请记住,浏览器和 Web 服务器并不总是按照我们期望的方式运行。一个著名的例子:2012 年移动版 Safari 开始缓存 POST 请求。开发商不高兴。
Query String
请求参数
Examples in ASP.Net MVC Razor syntax, but applicable in nearly any server processing language.
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.
...由于某些应用程序传统上使用带有查询 URL 的 GET 和 HEAD(在 rel_path 部分中包含“?”的那些)来执行具有显着副作用的操作,缓存不得将此类 URI 的响应视为新鲜的,除非服务器提供明确的到期时间。这特别意味着 HTTP/1.0 服务器对此类 URI 的响应不应从缓存中获取。
Appending a random parameter to the end of the CSS URL included in your HTML will force a new request and the server should respond with HTTP 200 (not 304, even if it is hasn't been modified).
将随机参数附加到 HTML 中包含的 CSS URL 的末尾将强制执行新请求,服务器应以 HTTP 200(不是 304,即使尚未修改)响应。
<link href="[email protected]" />
Of course, if we randomize the query string with everyrequest, this will defeat caching entirely. This is rarely/never desirable for a production application.
当然,如果我们对每个请求随机化查询字符串,这将完全破坏缓存。这对于生产应用程序来说很少/从不理想。
If you are only maintaining a few URLs, you might manually modify them to contain a build number or a date:
如果您只维护几个 URL,您可以手动修改它们以包含内部版本号或日期:
@{
var assembly = Assembly.GetEntryAssembly();
var name = assembly.GetName();
var version = name.Version;
}
<link href="[email protected]" />
This will cause a new request the first time the user agent encounters the URL, but subsequent requests will mostly return 304s. This still causes a request to be made, but at least the whole file isn't served.
这会在用户代理第一次遇到 URL 时产生新的请求,但后续的请求大多会返回 304。这仍然会导致发出请求,但至少不会提供整个文件。
Path Modification
路径修改
A better solution is to create a new path. With a little effort, this process can be automated to rewrite the path with a version number (or some other consistent identifier).
更好的解决方案是创建一条新路径。只需稍加努力,这个过程就可以自动化,用版本号(或其他一些一致的标识符)重写路径。
This answershows a few simple and elegant options for non-Microsoft platforms.
此答案显示了一些适用于非 Microsoft 平台的简单而优雅的选项。
Microsoft developers can use a HTTP module which intercepts all requests for a given file type(s), or possibly leverage an MVC route/controller combo to serve up the correct file (I haven't seen this done, but I believe it is feasible).
Microsoft 开发人员可以使用 HTTP 模块拦截给定文件类型的所有请求,或者可能利用 MVC 路由/控制器组合来提供正确的文件(我还没有看到这样做,但我相信这是可行的)。
Of course, the simplest (not necessarily the quickest or the best) method is to just rename the files in question with each release and reference the updated paths in the link
tags.
当然,最简单的(不一定是最快或最好的)方法是在每个版本中重命名有问题的文件并在link
标签中引用更新的路径。
TLDR
TLDR
- Change the file name or query string
- Use a change that only occurs once per release
- File renaming is preferable to a query string change
- Always set HTTP headers to maximize the benefits of caching
- 更改文件名或查询字符串
- 使用每个版本只发生一次的更改
- 文件重命名优于查询字符串更改
- 始终设置 HTTP 标头以最大化缓存的好处
回答by Andy Gee
I think renaming the CSS file is a far better idea. It might not suit all applications but it'll ensure the user only has to load the CSS file once. Adding a random string to the end will ensure they have to download it every time. The same goes for the javascript method and the apache methods above. Sometimes the simple answer can be the most effective.
我认为重命名 CSS 文件是一个更好的主意。它可能不适合所有应用程序,但它会确保用户只需加载一次 CSS 文件。在末尾添加一个随机字符串将确保他们每次都必须下载它。上面的 javascript 方法和 apache 方法也是如此。有时,简单的答案可能是最有效的。
Another solution is:
另一种解决方案是:
<FilesMatch "\.(js|css)$">
Header set Cache-Control "max-age=86400, public"
</FilesMatch>
This limits the maximum cache age to 1 day or 86400 seconds.
这将最大缓存时间限制为 1 天或 86400 秒。
回答by RobDigital
Please go read Tim Medora's answer first, as this is a really knowledgeable and great effort post.
请先阅读 Tim Medora 的回答,因为这是一篇知识渊博且付出巨大努力的帖子。
Now I'll tell you how I do it in PHP. I don't want to bother with the traditional versioning or trying to maintain 1000+ pages but I want to ensure that the user always gets the latest version of my CSS and caches that.
现在我会告诉你我是如何在 PHP 中做到这一点的。我不想打扰传统的版本控制或试图维护 1000 多个页面,但我想确保用户始终获得我的 CSS 的最新版本并缓存它。
So I use the query string technique and PHP filemtime()which is going to return the last modified timestamp.
所以我使用查询字符串技术和 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.
该函数返回文件的数据块被写入的时间,即文件内容被改变的时间。
In my webapps I use a config.php file to store my settings, so in here I'll make a variable like this:
在我的 webapps 中,我使用 config.php 文件来存储我的设置,所以在这里我将创建一个像这样的变量:
$siteCSS = "/css/standard.css?" .filemtime($_SERVER['DOCUMENT_ROOT']. "/css/standard.css");
and then in all of my pages I will reference my CSS like this:
然后在我的所有页面中,我将像这样引用我的 CSS:
<link rel="stylesheet" type="text/css" media="all" href="<?php echo $siteCSS?>" />
This has been working great for me so far on PHP/IIS.
到目前为止,这在 PHP/IIS 上对我来说效果很好。
回答by Aaron R
Yu might be able to do it in apache...
Yu也许可以在apache中做到这一点......
<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>