PHP内容为什么不被浏览器缓存?

5
我已经为一个涉及PHP/nginx的网站运行了一些测试,测试内容是各种浏览器如何缓存动态内容。
我得出结论:默认情况下,即使在响应中没有Cache-Control或Expires参数,即使我不发送POST请求,只是跟随链接到页面,php文件从不会从缓存中获取,甚至在移动浏览器中也是如此。相比之下,css/js/image文件则从缓存中获取。
这对我很有好处,因为我希望动态html总是命中后端,并且具有Varnish或自己的php/filesystem实现的缓存机制。
这通常是默认行为吗?顺便说一下,我正在使用会话cookie。
2个回答

3
首先:我不是专家,关于这个主题你可能会知道比我更多,但是我会让你对它的工作原理有一个基本的了解。
CSS、图片和Javascript文件(通常)直接由Web服务器提供,而不需要经过任何PHP脚本。因此,Web服务器会自己处理这些文件的缓存。
对于PHP内容,Web服务器会调用您的PHP脚本并返回状态码200(如果在脚本中没有错误或者没有明确地指定不同的状态码)。
现在看看这个链接:Caching Tutorial 在那里,它说:
如果响应中没有验证器(ETag或Last-Modified标头),并且它没有任何显式的新鲜度信息,它通常 - 但并不总是 - 被视为不可缓存。
也就是说,Web服务器不会将这些标头添加到PHP响应中。但是它会将它们添加到像图片、CSS、JS这样的静态资源中。
因此,对于未来对您网站的请求,浏览器知道(因为这些标头),该网站本身是不可缓存的,但是图片是可以缓存的。
如果您第二次请求网站,客户端将正常请求php脚本并再次获得正常响应,因为原始响应中没有包含任何缓存信息(这里没有什么特别的)。
现在上面的文章说:
当缓存存储了一个包括Last-Modified头的表示时,它可以使用它来询问服务器自上次看到它以来表示是否已经改变,使用If-Modified-Since请求。
所以基本上浏览器会询问Web服务器图片是否有更改,如果没有更改,服务器会返回“304 Not Modified”响应,而不添加实际的图像到响应中(<=这是缓存)。
正如我之前所说,如果没有明确设置,php脚本永远不会返回此状态代码。
因此,在涵盖基础知识之后,我们可以来到重要的部分:;-)
tl;dr或“如何缓存PHP页面”
首先,您应该阅读上述文章中的“编写高速缓存感知脚本”部分。
然而,一种解决方案是:
  1. 在您的php脚本响应中包含一些验证信息(例如“Last-Modified”头),使用header函数。
  2. 在脚本开始时检查“If-Modified-Since”头,如果适当,则返回状态码“304 Not Modified”(而无需运行其余脚本)。

1
当重新请求之前没有返回ExpiresCache-Control标头的资源时,浏览器应该无论内容类型如何都会再次查询服务器(毕竟,图像、CSS等也可以动态生成)。唯一的区别是真正的静态文件通常使用额外的Last-Modified和/或Etag响应标头进行服务,这允许浏览器缓存数据并使后续请求有条件(使用If-Modified-Since和/或If-None-Match请求标头)。如果内容是新鲜的,则服务器返回没有内容的304 Not Modified响应,并且浏览器从缓存中拉取它。这不会发生在动态脚本的输出中(默认情况下不会)。

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