加个 ?v=1 页面就更新了,为什么这招有时不管用

举报
yd_224417480 发表于 2026/11/04 09:21:52 2026/11/04
【摘要】 改了一张活动图,发上去,自己打开是新的,同事打开还是旧的。清一下缓存,好了。这个场景太常见,常见到大家总结出一条经验:在链接后面加个 ?v=1,强制更新。这条经验大部分时候确实有效,但它不是原理,是个巧合——而且有一类域名上,它根本不管用。想搞明白,得先知道一张图从服务器到你屏幕上,要过几道缓存。三道关卡,不是一道你打开一个网页,中间至少有三层东西可能给你旧内容:第一层是你自己的浏览器。它把...

改了一张活动图,发上去,自己打开是新的,同事打开还是旧的。清一下缓存,好了。

这个场景太常见,常见到大家总结出一条经验:在链接后面加个 ?v=1,强制更新。这条经验大部分时候确实有效,但它不是原理,是个巧合——而且有一类域名上,它根本不管用。

想搞明白,得先知道一张图从服务器到你屏幕上,要过几道缓存。

三道关卡,不是一道

你打开一个网页,中间至少有三层东西可能给你旧内容:

第一层是你自己的浏览器。它把图片、样式、脚本存在本地,下次打开同一个网页,先看本地有没有能直接用的。

第二层是 CDN 节点。你的站点通常不是从源站直接发给每个用户的,中间有许多台分布在各地的服务器帮你转发。这些机器也会存一份,用户就近取,快。

第三层才是源站——你真正放文件的那台服务器。

「清缓存好了」通常只说明问题在第一层:你的浏览器存了旧的,清掉就正常。但同事还是旧的,说明他那一层没清;如果所有人都还是旧的,问题很可能在第二层的 CDN 上。

浏览器凭什么觉得本地那份还能用

浏览器不傻,它每次都会问一句「这份缓存还能用到什么时候」,答案写在服务器返回的响应头里。

最常见的两个:

Cache-Control: max-age=86400

意思是「一天之内别来找我,直接用你存的那份」。这叫强缓存——在这一天里,浏览器压根不会发请求,打开网页的速度因此非常快,代价是这一天里你改了文件它也不知道。

另一个是:

ETag: "3f9a1c8b"

浏览器下次会带着这个编号去问服务器:文件还是 3f9a1c8b 这个版本吗?是的话服务器只回一个很短的回答「没变」(状态码 304),不用把图片重新发一遍。这叫协商缓存——每次都要问一句,但问得很便宜。

区别就在这:强缓存期间,浏览器不问;协商缓存每次都要问。所以「把缓存时间设短一点」能让你更快看到更新,代价是每次都要多问一趟。

?v=1 这招,靠的是「当成另一个文件」

现在回到那个土办法。同一个地址加不同参数,浏览器和 CDN 怎么理解?

它们理解的不是「同一个文件的新版本」,而是另一个地址。/banner.png?v=1 和 /banner.png?v=2 在它们眼里是两个完全不同的东西,各存各的。旧的还在,只是没人再要它了。

这就是这招有效的原因——它不是在「更新缓存」,它是在「绕过缓存」。

而产生的那点浪费也很真实:所有用户的浏览器里,那张旧图会一直躺到过期为止,没人清理。

为什么有些域名上它不管用

关键在 CDN 那一层的一个开关,叫忽略参数(有的地方叫「过滤参数」)。

打开这个开关,CDN 在找缓存时会先把 URL 里 ? 后面的部分抹掉,只按路径匹配。这样 /list?page=1、/list?page=2 都命中同一份缓存,命中率高,回源次数少,对视频、安装包这类文件是划算的。

代价是:你加的 ?v=2 也被抹掉了,于是它老老实实命中旧的那份,你还以为是自己没传上去。

各家 CDN 的默认值不太一样,大致规律是:网页小文件这类业务默认不忽略参数(因为页面和接口常靠参数区分内容),下载大文件、音视频点播这类默认开启忽略。所以同一招,在图片站上管用,在视频站上可能永远不管用——不是玄学,是缓存键不一样。

真正稳的做法:让文件名自己变

如果不想依赖「哪一层记不记得清」,就把版本写进文件名:

<img src="/img/banner.3f9a1c8b.png">

这个 3f9a1c8b 是文件内容的指纹。内容一变,指纹就变,文件名随之变,URL 变了,所有缓存层都会认为是新东西——不管它开没开忽略参数,也不管它缓了多久。

反过来,文件名不变的文件就可以设很长的缓存时间,一年都行。因为它的内容永远不会变,变了就是另一个名字。

配套的两条,缺一条就出问题:

  • 入口 HTML 不能长缓存。它是首页,引用了所有带指纹的文件。它要是被缓存一天,用户就一天看不到新版本。通常给它设 no-cache(每次都要和服务器确认)或者很短的过期时间。
  • 别把 no-cache 和 no-store 混着用。前者是「可以存但每次要确认」,后者是「完全不存」,性能和语义都不一样。

(注意:Cache-Control: no-cache 的名字很有迷惑性,它不是「不缓存」,是「用之前先确认」。)

几个容易搞错的细节

Ctrl+F5 只对你自己有效。强制刷新绕过的是你本机的缓存,用户不会按,同事也可能不会按。

「刷新页面」不等于「绕过缓存」。普通刷新会让浏览器重新验证,但不一定重下图片;开发者工具里看到 (from disk cache) 就是没发请求。

Age 和 X-Cache 这类响应头很有用。Age: 3600 说明这份内容是 CDN 一小时前存的;X-Cache: HIT 说明命中了 CDN 缓存。查「到底是哪一层给的旧内容」,看这两个比猜快得多。

公司的代理、运营商也可能插一层。尤其是内网访问外部图片时,删掉 CDN 缓存仍然看到旧图,不一定是 CDN 的问题。

收尾

缓存出问题,很少是因为「没更新」,多半是因为「你以为它会更新」。

排查的顺序其实就三步:先看响应头里 Cache-Control 给了多久;再看 Age / X-Cache 判断是不是 CDN 给的;最后确认请求的 URL 和缓存键是不是同一个。这三步走完,问题基本就定位了。

至于 ?v=1,把它当成应急手段就好——它能救一次上线,但它不会告诉用户「东西换了」,只是让所有人都不知道还有个旧的。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。