发布时间:2026-09-26 05:00 更新时间:2026-09-26 05:00 阅读量:0
改版上线最让人头疼的场景之一:本地改了模板,源站文件也确认更新了,浏览器无痕模式打开却是新样式,正常窗口和手机端看到的还是老页面。反复刷新、清空浏览器缓存,过一会儿又变回旧的。这种情况通常不是代码没生效,而是请求路径上有多层缓存在同时工作——浏览器强缓存、CDN边缘节点缓存,有时还有源站 Nginx 或 PHP 层的页面缓存。每一层都有自己的过期时间和缓存键,只清一层,其余层会把旧内容继续吐给访客。
要把这件事一次做对,思路是先把三层拆开看清楚,再按“由内到外”的顺序刷新,最后用 curl 逐层验证,而不是靠反复按 Ctrl+F5。
浏览器强缓存由响应头决定。源站返回 Cache-Control: max-age=86400 时,浏览器在 24 小时内不会向服务器发请求,直接从本地磁盘读,这时候无论你怎么刷新源站都没用。强缓存阶段连请求都不会发出,所以看服务器日志也查不到。想跳过它,普通刷新不够,需要强制刷新(Ctrl+F5 或 Shift+F5),或者在开发者工具的 Network 面板勾选 Disable cache。
CDN 边缘缓存由 CDN 服务商按自己的缓存键判断。多数 CDN 默认把“域名 + 路径 + 查询字符串”作为缓存键,有的默认忽略查询串,有的把 Query String 完整纳入。这直接决定了 style.css?v=20260901 这种带参数的引用能不能命中新文件:如果 CDN 配置忽略查询串,加版本号也拿不到新内容;如果纳入,加参数就能绕过旧缓存。改版时先到 CDN 控制台确认缓存键规则,再决定是加版本号还是直接刷新目录。
源站缓存比较隐蔽。Nginx 的 proxy_cache、fastcgi_cache,或者 WordPress 的页面缓存插件,都会在自己的缓存目录里存一份 HTML 或静态文件。源站缓存过期时间往往写得比 CDN 长,CDN 回源时拿到的可能还是源站缓存里的旧版本。三层里任何一层没刷新,改版都可能看不到效果。
顺序原则是由内到外:先让源站产出新内容,再让 CDN 回源取新,最后处理浏览器。具体分四步。
第一步,确认源站文件确实更新。改完模板后检查文件时间戳,别只信编辑器标题栏:
ls -l --time-style=full-iso /www/wwwroot/example.com/index.php
curl -I https://www.example.com/
第二步,清源站缓存。如果用 Nginx 缓存,删掉对应缓存目录并 reload;如果用插件缓存,先在后台清空页面缓存,再确认缓存目录已空。Nginx 缓存目录位置以你的配置为准,示例:
nginx -T | grep -i proxy_cache_path
rm -rf /www/server/nginx/cache/*
nginx -s reload
第三步,刷新 CDN。在 CDN 控制台提交“刷新 URL”或“刷新目录”,首页和改动的 CSS/JS/图片都要覆盖。刷新是异步的,提交后等一两分钟再验证。此时用带随机参数的 curl 直接打源站,确认源站返回的是新内容:
curl -s -H 'Host: www.example.com' \
'http://127.0.0.1/?nocache=20260901' | head -20
curl -sI 'https://www.example.com/?nocache=20260901' | grep -iE 'age|x-cache|cf-cache'
响应头里的 Age 表示该资源在 CDN 节点上已缓存了多久,X-Cache、CF-Cache-Status 之类的字段会写明 HIT 还是 MISS,具体字段名以你使用的 CDN 为准。若带随机参数仍是旧内容,说明源站缓存没清干净;若随机参数是新的、去掉参数变旧,说明 CDN 缓存还在。
第四步,处理浏览器。把静态资源的引用加上版本号或内容哈希,例如 style.css?v=20260901,前提是 CDN 缓存键包含查询串。同时把 HTML 的 Cache-Control 设为 no-cache 或较短 max-age,让页面本身不易被强缓存,静态资源再用长缓存加版本号。Nginx 里可以这样写:
location ~* \.(css|js|png|jpg|webp)$ {
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
location = /index.php {
add_header Cache-Control "no-cache, must-revalidate";
}
注意 no-cache 不是不缓存,而是每次都回源校验,和 no-store 的含义不同,别写反。改版期间不要把 HTML 设成 max-age=86400,否则下次改版同样会卡住。
几个容易踩的点:一是只清了浏览器缓存就以为搞定,CDN 节点上的旧副本还在;二是只刷新了首页,没刷新 CSS 和 JS,页面骨架是新的、样式是旧的,看起来像“没生效”;三是 CDN 缓存键忽略查询串,加版本号等于没加,这种情况要么改缓存键规则,要么改用文件名哈希,比如 style.abc123.css;四是源站和 CDN 的过期时间倒挂,源站缓存比 CDN 还长,CDN 回源永远拿到旧内容,建议源站缓存时间短于或等于 CDN。
长期来看,把“改版 = 改内容哈希 + 刷 CDN + 校验响应头”固化成流程,比每次临时清缓存省事。上线后可以用一条命令快速自检各层状态:
curl -sI https://www.example.com/ | grep -iE 'cache-control|age|etag|last-modified'
curl -sI https://www.example.com/style.css | grep -iE 'cache-control|age|etag'
改版不生效这件事,本质是缓存层级没对齐。按源站、CDN、浏览器由内到外的顺序处理,每一步都用响应头验证,而不是凭感觉刷新,就能把问题定位到具体某一层。下一次改版前,先把静态资源引用改成带哈希的形式,再确认 CDN 缓存键包含查询串,后续的改版会顺畅很多。
| 📑 | 📅 |
|---|---|
| Nginx map 指令实战:按 UA、Referer 与域名做条件分流 | 2026-09-25 |
| 网站根目录被写入异常PHP文件:时间线、属主与日志反查上传入口 | 2026-09-25 |
| WordPress定时任务被wp-cron拖慢:改用系统crontab配置与验证 | 2026-09-25 |
| 宝塔面板网站备份还原到另一台服务器:跨机迁移的完整流程 | 2026-09-25 |
| WordPress文章ID与固定链接优化:伪静态改动后旧链接兼容 | 2026-09-25 |
| WordPress中文名附件变乱码或404:编码链路排查 | 2026-09-26 |
| 宝塔面板升级后网站打不开:PHP扩展、Nginx配置与面板服务逐项回滚排查 | 2026-09-26 |
| 域名下PC站与m站SEO冲突:canonical、自适应与UA跳转取舍 | 2026-09-26 |
| WordPress后台被暴力撞库告警:登录限速与日志加固 | 2026-09-26 |
| 网站301与302混用导致权重分散:跳转类型选择与生效验证 | 2026-09-27 |