我正在尝试优化一个页面,但发现有些奇怪的行为。每次我点击页面链接时,所有资源都会从服务器获取,并以 200 响应。但是,当我刷新页面时(具体来说,F5在 Firefox 中),所有资源都会返回 304,因此页面加载速度当然会快得多。
在这两种情况下,主页都会返回 200。在刷新情况下,If-Modified-Since
标头会随请求一起发送到资源。但是,在“单击链接”情况下,标头不会发送。这是什么原因?我能控制它吗?
答案1
为了确定发生此行为的确切原因,请尝试使用 FF 插件 LiveHTTPHeaders 或 Firebug 查看服务器的响应主体 - 更具体地说,它们如何允许浏览器缓存。如果没有这些信息,我很难准确说出您为什么会出现此行为。但是,是的,您可以通过几种方式来控制它。
如果您知道资源不会改变,您可以明确告诉浏览器将对象缓存一段固定的时间。一个很好的办法是说缓存几年 - 然后只需稍微更改 URL 即可强制刷新(例如将http://.../images/test.jpg?1
1 替换为 2、3、4 等)。一些框架会通过附加最后修改的时间戳自动执行此操作。
1).htaccess 电子标签(来自http://stuntsnippets.com/etags-htaccess/)
FileETag MTime Size
<ifmodule mod_expires.c>
<filesmatch "\.(jpg|gif|png|css|js)$">
ExpiresActive on
ExpiresDefault "access plus 1 year"
</filesmatch>
</ifmodule>
完整文档:http://httpd.apache.org/docs/2.0/mod/core.html
2).htaccess Cache-Control(来自http://www.askapache.com/htaccess/apache-speed-cache-control.html)
# 480 weeks
<filesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=290304000, public"
</filesMatch>
# 2 DAYS
<filesMatch "\.(xml|txt)$">
Header set Cache-Control "max-age=172800, public, must-revalidate"
</filesMatch>
# 2 HOURS
<filesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=7200, must-revalidate"
</filesMatch>
答案2
为什么会发生这种情况
这种行为可能归因于浏览器缓存,但混乱是由于响应的显示方式。这是一个很大的假设,整个答案都取决于此,所以如果这是不正确的,请原谅我。
我发现 Chrome 浏览器(按 F12,‘网络’选项卡)比 Firefox 更能说明这一点。
每次我点击页面的链接时,所有资源都会从服务器获取,并以 200 响应。
可能发生的情况是,当你“点击链接”(与直接输入 URL 相同)时,你会看到 200 个响应,其中既有真实的请求,也有浏览器缓存的响应。这是正常行为。Chrome 通过在网络选项卡中针对每个资源明确声明“来自缓存”来说明“来自缓存”响应。我相信 FF 将此说明为灰色的时间线中的回应。
在这两种浏览器中,当从缓存中检索项目时,它们仍会显示状态响应。这是来自最后一个服务器响应,但这仍然是一个缓存的响应。
但是,当我刷新页面(具体来说,在 Firefox 中按 F5)时,所有资源都返回 304,当然,页面加载速度也更快了。
当您按下 F5 时,您将强制发送请求,但并非完全忽略缓存,而是在服务器上再次检查缓存是否已更改。您的请求标头包含,If-Modified-Since
因为它仍可从缓存中获得。系统将返回 304,并且您的浏览器将使用缓存版本,确信服务器版本未更改。
关注链接= 使用缓存数据。
F5= 再次发送请求。
Ctrl+F5= 再次发送请求但也忽略本地缓存。
在两种情况下,主页均返回 200。
浏览器缓存可能已针对主页(可能默认禁用所有 .html 内容)通过为其返回的响应标头禁用。因此,它无法If-Modified-Since
在刷新的请求中发送,因为它在本地缓存中不存在,因此没有日期可以与内容进行比较。由于请求中没有If-Modified-Since
发送,服务器必须使用完整的页面内容响应另一个 200。
在刷新情况下,If-Modified-Since 标头会随对资源的请求一起发送。
因为资源项可从缓存中获取,所以有一个要发送的日期 - 即资源项被添加到浏览器缓存的日期。
然而,在“点击链接”的情况下,情况并非如此。这是什么原因?我能控制它吗?
因为浏览器在从本地缓存中检索时不会发送 If-Modified-Since 标头。200“响应”是缓存的响应。您无需控制那像这样。
这些都不能解释为什么按 F5 时加载速度会更快。你确定这是正确的吗?
另外,请注意浏览器的“启发式缓存”。这是浏览器在缓存未由响应标头明确定义时采取的行为,本质上是一种“最佳猜测”行为。当然,每个浏览器的情况都不同。
答案3
对我来说,这听起来像是浏览器设置,浏览我(Windows 7)上网本上的 Firefox 中看到的选项,我看不到任何可以让你控制它的东西。
所以,我认为答案恐怕是否定的。
答案4
如果您包含了两种场景的请求和响应标头的示例,那将会很有帮助。
显式刷新会导致浏览器在请求中包含 prama: no-cache - 这意味着所有中间缓存(包括代理)都必须将请求转发到原始服务器。当您单击链接时,内容可能来自您的浏览器缓存、中间代理、反向代理或原始服务器。
所有资源都返回 304,当然,页面加载速度更快
但是,如果您在提供内容时附带允许浏览器缓存的指令(即 expires 或 cache-control: max-age 指令),您将获得更快的响应。条件请求仅在处理非常大的文件(PDF、视频等)时才真正加快访问速度。请注意,大多数浏览器在从本地缓存中获取时都会针对此类操作报告 200 状态 - 但这比引用回原点要快得多。
在刷新情况下,If-Modified-Since 标头会随对资源的请求一起发送。然而,在“点击链接”情况下,则不会
真的吗?你确定吗?
如果您没有包含任何 max-age / expires 缓存指令,则可能会发生这种情况 - 这是一件非常愚蠢的事情,我从未测试过它的行为方式。