改完样式,自己刷新看是对的,客户打开还是旧的。你让他清缓存,他清了,好了。下一次改,同样的事情再来一遍。
这不是客户的问题,是网站少做了一件事。
为什么会这样
浏览器为了快,会把样式表、脚本、图片存在本地。下次访问同一个地址时,直接用本地的副本,不再去服务器要。
关键在于浏览器判断”是不是同一个文件”,看的是地址。
你的样式表地址是 /assets/style.css。你改了文件内容,但地址没变。在浏览器看来,这还是它已经存下来的那个文件,没必要重新下载。
更麻烦的是中间可能还有一层 CDN,它也在按地址缓存,而且缓存时间通常更长。
所以会出现这个局面:服务器上是新的,CDN 上是旧的,客户浏览器里也是旧的,而你自己因为反复调试早就手动清过缓存,看到的是新的。你完全意识不到别人看到什么。
解法:让地址跟着内容变
思路很简单——内容变了,就换一个地址。新地址浏览器和 CDN 都没见过,只能去取新的。
两种常见做法:
一、在地址后面加版本参数。
把 /assets/style.css 写成 /assets/style.css?v=1712345678。这个数字用文件的最后修改时间自动生成——改了文件,数字自动变,地址自动变。
好处是实现简单,文件名不用动。我们自己的站用的就是这种,值直接取文件修改时间,不需要人记得改。
二、把内容哈希写进文件名。
/assets/style.a3f9c2.css,中间那串是文件内容算出来的。内容变了哈希就变,文件名就变。
这种更彻底,而且对某些 CDN 更保险——有的 CDN 在配置不当的情况下会忽略查询参数,这时候第一种做法就失效了,而文件名变了是绝对绕不过去的。
字体文件我们用的是这种,因为字体是从样式表里按固定路径引用的,改文件修改时间对它不起作用。
关键在于”自动”
这里最容易出错的不是用哪种方法,而是版本号是不是自动更新的。
我们见过不少网站是手写版本号的:?v=2,改一次内容手动改成 ?v=3。这个做法在第一个月有效,然后就会开始漏——赶时间的时候忘了改,或者改了文件忘了这回事。
而漏掉的表现恰恰是”部分用户看到旧的”,这种问题你自己测不出来。
凡是依赖人记得的环节,迟早会被忘掉。版本号必须由构建过程或者程序自动生成,这是唯一可靠的做法。
怎么确认自己的站有没有做
三十秒可以查:
打开你的网站,右键”查看网页源代码”,找到引用样式表的那一行。看它长什么样:
href="/style.css" —— 没有版本号,会有这个问题。
href="/style.css?ver=6.4.3" —— 有版本号,但如果这是系统版本号(比如 WordPress 版本),那么只有系统升级时才会变,你改样式它不变,等于没有。
href="/style.css?ver=1712345678" 或者 href="/style.a3f9c2.css" —— 这是对的。
再验证一次:改一点样式,重新部署,再看那个数字有没有变。变了就是自动的。
做对之后可以顺便省一笔
版本号还有个附带好处,很多人没利用起来。
既然改动一定会换地址,那么这些资源就可以设置极长的缓存时间——一年,甚至标记为”永不改变”。反正内容一变就是新地址,旧地址被缓存多久都不影响。
这样客户第二次访问时,样式表、脚本、字体全部直接用本地的,一个字节都不用下载。对重复访问的用户来说,这是实打实的加速。
没有版本号的话就不敢这么设——设长了改动没法生效,设短了每次都要重新验证。版本号是长缓存的前提。
这里有个我们踩过的坑值得一提:配置缓存规则的时候,如果通配的兜底规则和针对资源的规则同时命中同一批文件,某些系统是把两条规则的值拼接而不是覆盖。结果是资源同时带上了”缓存 10 分钟”和”缓存一年”两个值,实际生效的是前面那个——一年的长缓存形同虚设,而且完全不报错。
发现它只能靠一件事:实际去看一次响应头,而不是相信配置界面上写了什么。
图片也一样
这个问题在图片上同样存在,而且更隐蔽。
你换了一张产品图,文件名没变,直接覆盖上传。你自己看是新的(你刚上传过),客户看到的还是旧图,可能持续几天。
处理办法一样:换图就换文件名。不要覆盖同名文件。
还有一个相关的坑:CDN 会缓存 404。如果一张图还没上传就有人(或者爬虫)访问过那个地址,CDN 记住了”这里没东西”。之后你把图传上去了,访客看到的还是空白。
这个我们踩过两次。识别方法是在图片地址后面加一个随机参数——如果加了参数能显示,那就是缓存问题,不是文件问题。
一句话总结
如果你现在的流程里有”改完让客户清一下缓存”这一步,那不是正常操作,是有个技术问题没解决。
正常的网站,改完部署,所有人下一次访问就是新的,不需要任何人做任何事。
我们交付的项目里资源版本号是自动生成的,样式脚本按文件修改时间、字体按内容哈希。这不是加分项,是不做就会持续出问题的基础配置。