You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让浏览器或PHP对fetch()请求进行缓存?

如何让PHP与浏览器自动处理fetch请求的缓存?

这本质上是和《fetch()如何发起不缓存请求》相反的问题。

现有客户端代码:

<div onclick="fetch('/data.php').then(r => r.text()).then(s => console.log(s));">Click me</div>

服务端PHP代码:

<?php echo "hello"; /* 实际上,这里可以是更多数据,且/或后续会更新为其他内容 */ ?>

多次点击“Click me”时,请求会反复通过网络发送,响应码始终为200,说明浏览器和PHP都未启用缓存机制。我们希望避免数据未更新时的重复网络传输。

我自己想到一种方案:服务器返回数据时附带时间戳元数据,客户端把时间戳存在JS变量里,下次请求前先调用接口获取最新时间戳,对比后仅在数据更新时才请求/data.php:

fetch('/get_last_modification_date.php').then(r => r.json()).then(data => {
    if (data['timestamp'] != timestamp)
        fetch('/data.php')...       // 仅当有新数据时才发起请求
});

这个方案可行,但这类工作本该由浏览器+PHP的缓存机制自动完成,怎么让它们自动处理缓存?


核心实现:利用HTTP缓存头实现自动缓存控制

要让浏览器和PHP自动处理缓存,关键是通过HTTP响应头约定缓存规则,让浏览器自动缓存数据并在需要时验证缓存有效性,无需额外写预检逻辑。

1. PHP端配置缓存响应头

PHP需要返回两类关键头:缓存控制规则,以及数据更新标识(Last-Modified/ETag),用于验证缓存是否过期。

方案一:基于时间戳的Last-Modified验证

适合数据更新时间可以明确获取的场景(比如文件修改时间、数据库更新时间):

<?php
// 模拟数据最后修改时间(实际项目中替换为真实的更新时间)
$lastModifiedTime = strtotime("2024-05-20 14:30:00");

// 设置Last-Modified响应头(必须是GMT格式)
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModifiedTime) . " GMT");

// 检查浏览器发送的If-Modified-Since请求头
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
    $clientModifiedTime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
    // 如果客户端缓存的时间不早于服务器的最后修改时间,返回304
    if ($clientModifiedTime >= $lastModifiedTime) {
        header("HTTP/1.1 304 Not Modified");
        exit; // 停止输出,不返回数据
    }
}

// 设置缓存控制:允许公共缓存,有效期1小时(可根据需求调整max-age值)
header("Cache-Control: public, max-age=3600");

// 输出实际数据
echo "hello";
?>
方案二:基于唯一标识的ETag验证

适合数据更新无法用时间戳准确判断的场景(比如动态生成的内容,时间戳不变但内容已更新):

<?php
// 实际业务数据
$data = "hello";
// 生成数据的唯一ETag(这里用MD5哈希,也可以用其他唯一标识逻辑)
$etag = md5($data);

// 设置ETag响应头
header("ETag: \"$etag\"");

// 检查浏览器发送的If-None-Match请求头
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
    $clientEtag = trim($_SERVER['HTTP_IF_NONE_MATCH'], '"');
    // 如果ETag匹配,说明缓存有效,返回304
    if ($clientEtag === $etag) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }
}

// 设置缓存控制规则
header("Cache-Control: public, max-age=3600");

// 输出数据
echo $data;
?>

2. 客户端fetch的默认行为

默认情况下,fetch会自动遵循HTTP缓存规则:

  • 第一次请求:浏览器发送完整请求,获取200响应和数据后,自动缓存数据及对应的Last-Modified/ETag
  • 缓存有效期内:浏览器直接读取本地缓存,不发起网络请求
  • 缓存过期或数据更新:浏览器会发送带If-Modified-Since或If-None-Match头的请求,PHP验证后返回304(不传输数据)或200(新数据)

无需修改原有的客户端fetch代码,只要确保没有显式设置cache: "no-store"或cache: "reload"这类禁用缓存的选项即可。


内容的提问来源于stack exchange,提问作者Basj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:45:30