首页 > 技术文章 > PHP设置HTTP缓存头

zzl-cn 2017-07-12 17:32 原文

对于PHP输出的内容,如果不是需要经常变动的内容(例如伪静态的一些页面,PHP输出JS或者CSS),使用PHP合理设置HTTP响应头添加缓存设置,让浏览器尽可能缓存下内容,在刷新和再次访问同样内容时,便不需要再次请求浏览器,从而能够大幅减少服务器的响应次数,同时浏览器呈现页面也会加快了,这是非常有用的一个技巧。

1、输出Cache-Control头:

header('Cache-Control:max-age=120');


这个的输出是表明让浏览器缓存120秒。这个指令很有用,但是局限性在于,刷新这个页面时还是会重新请求,所以你会感觉这个头好像没什么作用,但是对于一些输出的JS、CSS内容时是有用的,也就是说你刷新的页面不是它本身,而只是引用了设置有此头的PHP文件的话,它就会在你指定的时间内从本地缓存中读取内容而不会请求服务器。同时通过超链接过来的已经请求过的页面时,你也会看到浏览器从本地cache里读取而不用通过服务器。

2、更高级玩法:通过设置Last-Modified、Expires头设定缓存
如下面这段代码


<?php
$interval=120; //2分钟
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])){
    // HTTP_IF_MODIFIED_SINCE即下面的: Last-Modified,文档缓存时间.
    // 缓存时间+时长.
    $c_time = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])+$interval;
    // 当大于当前时间时, 表示还在缓存中... 释放304
    if($c_time > time()){
        header('HTTP/1.1 304 Not Modified');
        exit();
    }
}
header('Cache-Control:max-age='.$interval);
header("Expires: " . gmdate("D, d M Y H:i:s",time()+$interval)." GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
echo ' - <a href="">点击重新载入本页面</a><br />';


当浏览器首次访问时,请求头不会带HTTP_IF_MODIFIED_SINCE这个东西,所以我们就设置了三个头。
一个就是刚才第1点,Cache-Control头,告诉让浏览器自己缓存个120秒。
第二个头Expires是表明,在当前时间的120秒后缓存失效,浏览器会在120秒后把缓存失效,再次请求时会到服务器端请求而不是本地。
第三个头Last-Modified则是说明这个文档最后修改时间。可以看出输出的当前时间。

当浏览器再次访问时(刷新页面),浏览器因为在第一次时接收到了Last-Modified,它便会根据这个时间去检查服务器的文档是否更新过,也就是会把这个时间用HTTP_IF_MODIFIED_SINCE这个东西带过去,于是也就有了第一个花括号内容的判断。而花括号内再次根据这个时间加上你设置的时间(120秒),看看是不是超出了当前的时间time(),如果超出了,那就是还在缓存期内,帮直接返回304,然后直接退出。这时候浏览器便会自动用缓存的内容。这样子做,服务器返回的内容就很短,只是一个304响应头而已,而内容不需要返回,这可大大节省网络流量,显然浏览器的响应速度也会感觉明显快了。

按F5刷新或者按浏览器的刷新按钮时,你将发现2分钟内你的PHP请求将是304状态返回。
强制刷新(CTRL+F5)时,浏览器不会带HTTP_IF_MODIFIED_SINCE这个东西去判断,所以同正常浏览一样,返回200状态。这个逻辑是正常的,因为强制刷新本就相当于完全请求一遍最新内容。

浏览器头中的缓存设置虽然技巧虽小,但是在web应用中非常有用。合理利用浏览器的缓存,尽量避免重复内容的请求,一个页面少了几十KB的请求,流量大的网站一天能够节省几百M甚至几G的网络流量。这对提升用户体验来说也是一个相当重要的设置项。

推荐阅读