WordPress站点Safari缓存异常:始终触发XMLHttpRequest请求求助
解决Safari下Nginx FastCGI Cache不缓存WordPress页面的问题
这问题确实够诡异的,我之前帮朋友排查过类似的情况,咱们一步步拆解来解决:
先搞清楚核心现象的本质
你提到两个关键差异:
- WordPress页面在Safari里不返回
X-Cache,但独立PHP页正常 - Safari会先发起常规GET,然后强制触发XHR请求
这说明问题大概率出在WordPress输出的缓存头干扰,或者Nginx缓存规则对WordPress请求的特殊处理,再或者是页面JS在Safari下的异常行为。
第一步:排查Safari中常规GET请求的响应头
打开Safari开发者工具(快捷键Cmd+Opt+I),切换到「网络」面板,刷新页面后找到第一个GET请求(就是页面本身的请求),检查响应头里的这些字段:
X-Cache:有没有这个字段?如果没有,说明Nginx根本没缓存这个请求Cache-Control:是不是no-cache, must-revalidate这类禁止缓存的值?WordPress默认会输出这类头,而Safari对这类头的执行比Chrome/Firefox更严格Pragma:如果有no-cache,也会影响Safari的缓存判断
对比Chrome里相同页面的响应头,如果发现Safari里的缓存头更严格,那就是WordPress的输出覆盖了Nginx的缓存配置。
第二步:调整Nginx配置,强制覆盖缓存规则
WordPress经常会自己输出缓存控制头,这时候需要Nginx强制覆盖它。修改你的FastCGI Cache配置:
# 在http块或server块里添加缓存基础配置 fastcgi_cache_path /var/cache/nginx/wp_cache levels=1:2 keys_zone=WP_CACHE:10m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; # 只缓存成功和重定向状态码 fastcgi_cache_valid 200 301 302 1h; fastcgi_cache_valid 404 1m; # 关键:强制添加缓存头,用always确保所有响应都带上 add_header Cache-Control "public, max-age=3600" always; add_header X-Cache $upstream_cache_status always; # 在PHP处理的location块里启用缓存 location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/run/php/php8.2-fpm.sock; # 换成你的PHP-FPM实际路径 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # 启用缓存 fastcgi_cache WP_CACHE; # 只有登录用户才绕过缓存(根据WordPress的登录Cookie) fastcgi_cache_bypass $http_cookie_wordpress_logged_in_.*; fastcgi_no_cache $http_cookie_wordpress_logged_in_.*; # 重点:注释掉对XHR请求的缓存绕过规则! # 很多默认配置里会加这两行,导致XHR请求不缓存,正好命中你的异常场景 # fastcgi_cache_bypass $http_x_requested_with; # fastcgi_no_cache $http_x_requested_with; }
修改后重启Nginx,再用Safari测试,看常规GET请求是否返回X-Cache: HIT。
第三步:排查页面JS的XHR触发逻辑
如果常规GET请求已经命中缓存,但Safari还是会发起XHR请求,那问题出在页面的JS代码上:
- 打开Safari开发者工具的「网络」面板,找到XHR请求,查看「启动器」标签,定位发起这个请求的JS文件和代码行
- 检查是不是主题或插件的JS在Safari下有兼容性问题,比如判断浏览器UA后强制用XHR加载内容,或者懒加载逻辑出错
- 暂时禁用所有WordPress插件,切换到默认主题(比如Twenty Twenty-Four),看XHR请求是否消失,以此排查是哪个插件/主题导致的
最后补充一个常见坑点
Safari对Cookie的处理比较严格,如果WordPress页面带有wordpress_test_cookie这类测试Cookie,而你的Nginx缓存Key包含了$http_cookie,那每个带Cookie的请求都会生成独立的缓存条目,甚至直接不缓存。确保你的fastcgi_cache_key里不要包含$http_cookie,除非你确实需要按Cookie区分缓存内容。
内容的提问来源于stack exchange,提问作者Stephen
相关产品推荐
相关产品推荐

