safari 浏览器的一次问题定位
2025年7月5日 17:27
背景
批量上传资源型文件, 需要先获取对应每份文件的 ID 标识进而上传。 简而言之, 上传链路为: 并行获取标识 -- 并行触发上传。
问题
chrome 浏览器上链路正常, safari 浏览器并行获取标识请求被缓存后只会进行单次触发。
问题定位
- 针对触发链路进行断点 debug , 不得不说, safari 的 debug 机制实在是不友好。 发现断点确实命中多次, 说明代码链路正常执行。
- 查看接口请求
查看标头相关字段, 并未发现缓存机制相关字段 (Cache-Control
), 结合
www.raymondcamden.com/2015/07/16/…
猜测是请求被 safari 浏览器缓存。
问题解决
- 给该请求添加随机数 ID (
nanoid
生成)标识不同请求 例如
// 在 URL 后添加时间戳参数
const url = `/api/data?t=${Date.now()}`;
// 或使用随机数
const url = `/api/data?r=${Math.random().toString(36).substring(2)}`;
2. 设置请求的缓存方式
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
附 Cache-Control
的一些用法说明
维度 | 请求头(Request Headers) | 响应头(Response Headers) |
---|---|---|
控制方 | 客户端(浏览器) | 服务器 |
作用对象 | 当前请求的处理方式 | 返回的资源的缓存策略 |
核心目的 | 声明浏览器对缓存的偏好(如是否强制验证) | 规定资源如何被缓存(如有效期、存储位置) |
优先级 | 可临时覆盖响应头的缓存策略(如强制刷新) | 主导缓存行为,是缓存规则的基础 |
请求头中的 Cache-Control
浏览器在发送请求时添加,用于 声明本次请求的缓存处理意愿。
常见指令及作用:
指令 | 含义 | 典型场景 |
---|---|---|
no-cache |
跳过强缓存,直接向服务器验证缓存有效性(触发协商缓存)。 | 强制刷新(Ctrl+F5) |
no-store |
完全忽略缓存:不读取缓存,且要求服务器返回原始数据(不缓存响应)。 | 敏感数据请求(如银行页面) |
max-age=0 |
等效于 no-cache ,强制验证缓存有效性。 |
普通刷新(F5) |
max-stale=300 |
允许使用过期缓存,但过期时间不超过 300 秒。 | 弱网环境下容忍旧缓存 |
响应头中的 Cache-Control
服务器在返回响应时添加,用于 规定资源如何被缓存。
常见指令及作用:
指令 | 含义 | 典型场景 |
---|---|---|
max-age=3600 |
资源有效期 3600 秒(强缓存),期间浏览器直接使用缓存。 | 静态资源(JS/CSS/图片) |
no-cache |
可缓存,但每次使用前必须向服务器验证(强制协商缓存)。 | 频繁变化的资源(如实时数据) |
no-store |
禁止任何缓存(浏览器和代理均不可存储)。 | 敏感数据(如登录页) |
public |
允许浏览器和代理服务器(CDN)缓存资源。 | 公共资源(如图片库) |
private |
仅允许浏览器缓存,禁止代理服务器缓存。 | 用户私有数据(如个人中心) |
immutable |
资源永不变,浏览器直接使用缓存而不验证(适用于哈希命名的静态文件)。 | 文件名带哈希的静态资源 |