【问题标题】:php content never cached by browser?php内容从未被浏览器缓存?
【发布时间】:2016-05-25 07:17:30
【问题描述】:

我已经对一个网站进行了一些测试,涉及动态内容(在本例中是通过 PHP/nginx)如何被各种浏览器缓存。

我得出的结论是,默认情况下,php 文件永远不会从缓存中提取,即使在移动浏览器中,即使响应中没有 Cache-ControlExpires 参数,即使我没有发送 POST 请求,我只需点击该页面的链接即可。它们总是被重新下载。相比之下,css/js/image 文件是从缓存中获取的。

这对我有好处,因为我希望动态 html 始终打到后端,并以 Varnish 或我自己的 php/文件系统实现的形式拥有缓存机制。

这是默认情况下通常预期的行为吗?顺便说一句,我正在使用会话 cookie。

【问题讨论】:

    标签: php caching mobile browser nginx


    【解决方案1】:

    首先:我不是专家,很可能你可以在这个主题中添加比我现在做的更多的东西,但它应该能让你对它的工作原理有一个基本的了解。

    CSS、图像和 Javascript 文件(通常)由网络服务器直接提供,而无需访问任何 php 脚本。因此,网络服务器会自行处理这些文件的缓存。

    对于 PHP 内容,网络服务器会调用您的 php 脚本并返回状态码 200(如果没有错误或脚本中没有明确指定不同)。

    现在看这个链接:Caching Tutorial

    上面写着:

    如果响应中没有验证器(ETag 或 Last-Modified 标头),并且没有任何明确的新鲜度信息,则通常(但并非总是)将其视为不可缓存。

    也就是说,网络服务器不会将这些标头添加到 php 响应中。但它会将它们添加到静态资源中,例如图像、css、js。

    因此,对于您网站的未来请求,浏览器知道(由于这些标头)该网站本身不可缓存,但图像是。

    如果您第二次请求该网站,客户端只会正常请求 php 脚本并再次获得正常响应,因为原始响应中不包含缓存信息(这里没什么特别的)。

    现在上面的文章说:

    当缓存存储了包含 Last-Modified 标头的表示时,它可以使用 If-Modified-Since 请求来询问服务器自上次看到后表示是否已更改。

    所以基本上浏览器会询问网络服务器图像是否更改,如果没有,服务器将返回“304 Not Modified”响应,而不会将实际图像添加到响应中(

    正如我之前所说,如果没有明确设置,php 脚本永远不会返回此状态代码。 因此,在介绍了基础知识之后,我们可以进入重要的部分:;-)

    tl;dr 或“如何缓存 PHP 页面”

    您可能应该先阅读上面文章的“编写缓存感知脚本”部分。

    但是一种解决方案是:

    1. 在 php 脚本的响应中包含一些验证信息(例如“Last-Modified”标头)(使用 header 函数)
    2. 在脚本开头检查“If-Modified-Since”标头,并在适当的情况下返回状态代码“304 Not Modified”(不运行脚本的其余部分)。

    【讨论】:

      【解决方案2】:

      当重新请求之前返回的没有 ExpiresCache-Control 标头的资源时,浏览器应该总是再次查询服务器,无论内容类型是什么(毕竟,图像、CSS 等也可以动态生成)。

      唯一的区别是,真正的静态文件通常带有额外的Last-Modified 和/或Etag 响应标头,它们允许浏览器缓存数据并使后续请求有条件(使用If-Modified-Since 和/或@ 987654326@ 请求标头)。如果内容是新鲜的,则服务器返回没​​有内容的304 Not Modified 响应,并且浏览器从缓存中拉取它。动态脚本的输出不会发生这种情况(嗯,默认情况下不会)。

      【讨论】: