如何使用控制缓存头?

9
我下载了Google Chrome的速度跟踪器来查看我的网站性能,它告诉我需要为某些文件启用缓存,如style.css、图像等。
我读到下面的PHP代码应该告诉浏览器缓存HTML内容。我写了一个快速的PHP页面,上面放了几张图片,并在顶部(在头部发送之前)粘贴了以下代码以测试它的工作方式。
Header("Cache-Control: public, max-age=3600, must-revalidate");

当我回到速度跟踪器的分析时,它显示如下内容:
摘要: 来自缓存:false 请求头: Pragma: no cache Cache-Control: max-age=0
但在响应头中... Cache-Control: public, max-age=3600, must-revalidate(正是我指定的)
我有点困惑,发生了什么...?当它说来自缓存:false时,是否意味着来自服务器缓存而不是客户端缓存?

请及时向我报告您的发现。 - user611924
4个回答

4
关键是must-revalidate:这意味着客户端正在询问服务器文件是否已更改。如果您不处理此情况,浏览器将获取新副本。
阅读Mark Nottingham的出色缓存教程以获取更多信息。作为PHP实现的示例,您可以使用我的代码
查看$_SERVER['HTTP_IF_NONE_MATCH']$_SERVER['HTTP_IF_MODIFIED_SINCE']来验证客户端,并注意两个标头都可能包含恶意代码。 ;)

那么你的意思是,使用这种方法可以缓存“图像、CSS、脚本等”,而无需修改服务器配置? - payling
是的,静态文件由服务器处理。可执行文件(PHP、SSI、CGI)必须自行处理,因为服务器无法知道它们会生成什么内容。 - fuxia
这个答案是错误的 - 如果正确实现,提供的头信息将强制缓存内容。 - symcbean
当你说“如果实现得当...”,你能详细说明一下吗?非常感谢。 - payling
请看我在其他地方的回答 - 我没有完全研究你的问题,以确定header()调用是否正常工作。 - symcbean
只是为了澄清,“must-revalidate”部分意味着没有客户端或代理应该使用过期的缓存,如果页面返回错误代码,则不应将其缓存。 - symcbean

0
当它说“from cache: false”时,这是否意味着从服务器缓存而不是客户端缓存?^ 这是指客户端缓存。
以这种方式设置缓存将覆盖您的PHP文件,但您仍需在服务器端实现其他东西来缓存您的图像、CSS、脚本等。如果您的服务器支持,可以使用.htaccess 来完成这项工作。
例如,以下是我在几个站点上使用的.htaccess文件。
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)(\.gz)?$">
  Header set Expires "Thu, 15 Apr 2012 20:00:00 GMT"
  Header unset ETag
  FileETag None
</FilesMatch>

我希望它能像把一个 .htaccess 文件放到我的站点目录中一样简单。我们公司租用的是一个 IIS6 服务器(不使用 .htaccess 文件),我除了通过 FTP 进入站点目录之外没有直接控制服务器的权限... - payling
@payling:IIS可能有自己的配置处理程序来完成同样的事情,但如果其他方法都失败了,您可以使用PHP文件来提供您的css / etc,以以下方式:<?php headers("..."); echo file_get_contents("yourfile.css"); ?>。不过,只有在必要时才应该这样做。 - pinkgothic

0

我不熟悉这个工具,但在任何浏览器使用缓存头获取内容之前,它都无法缓存。看起来您的服务器正在发送预期的头文件,页面应该被浏览器缓存 - 您的浏览器现在应该已经有了一个副本。如果您尝试再次获取相同的页面,则将从缓存而不是原始服务器获取(假设1小时时间限制尚未过期)。

请注意,某些浏览器会将刷新请求解释为显式请求以忽略缓存并再次获取页面 - 尝试通过链接访问它,而不是点击刷新按钮。

C.


据我所知,我发布的代码对我没有任何作用。我使用Fiddler分析了流量,无论有没有代码,浏览器都从缓存的图像/样式表中绘制。这让我感到困惑,因为Speed Tracer的结果与之相反...我将花更多时间找出发生了什么。 - payling

0

你需要了解这些 Cache-Control 头字段 指令的实际含义:

  • public:

    表示响应可以被任何缓存缓存,即使它通常是不可缓存的或仅在非共享缓存中可缓存。 (有关详细信息,请参见Authorization, section 14.8。)

  • max-age=3600 指定响应在3600秒内为新鲜状态:

    当 max-age 缓存控制指令存在于缓存的响应中时,如果其当前年龄大于给定的年龄值(以秒为单位),则该响应已过期,需要在新请求资源时重新验证。响应上的 max-age 指令意味着响应是可缓存的(即“public”),除非还存在其他更严格的缓存指令。

  • must-revalidate 指定缓存必须在使用已过期的缓存响应之前重新验证它:

    当缓存接收到包含 must-revalidate 指令的响应时,缓存在使用已过期的条目响应满足后续请求之前,必须先通过与源服务器重新验证来确保其仍然有效。 (即,如果仅基于源服务器的 Expires 或 max-age 值,缓存响应已过期,则缓存必须每次进行端到端重新验证。)[...] 服务器应该仅在实体的请求未能重新验证可能导致不正确操作时(例如未执行的金融交易)才发送 must-revalidate 指令。

现在这些指令的预期含义就是这样。

但实际情况总是有所不同:特别是must-revalidate并不仅被解释为只在缓存响应过期后重新验证,而是必须在每个后续请求上重新验证或根本不能缓存(这可能是为什么它在后续请求中发送Cache-Control: max-age=0的原因)。

“From Cache: false”似乎表明响应并非来自缓存,而是直接来自服务器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接