你有没有遇到过这种情况:明明已经把网站上的图片换成了新的,可打开网页时看到的还是老样子?改了头像,朋友说没变;更新了产品图,客户却说没看到。这时候很多人第一反应就是——是不是缓存搞的鬼?
缓存确实是常见“嫌疑人”
浏览器为了加快网页加载速度,会把一些资源存到本地,比如CSS、JS,还有图片。当你第二次访问同一个页面时,它不会重新下载所有内容,而是直接从电脑里拿之前存好的文件。这个机制叫缓存,本意是好事儿,但更新图片时就容易“好心办坏事”。
比如你在公司后台上传了一张新宣传图,地址还是原来的 /images/banner.jpg,浏览器一看:“这文件我有啊”,直接显示旧图,根本不找服务器要新的。用户刷新几十次都没用,因为普通刷新(F5)很多时候也不会跳过缓存。
怎么判断是不是缓存的问题?
最简单的办法是换个环境看看。用手机4G网络打开,或者在电脑上开个无痕窗口(Chrome的Ctrl+Shift+N)。如果这时候能看到新图,那基本就能锁定是浏览器缓存导致的旧图残留。
另一个方法是看开发者工具。按F12打开控制台,切换到Network标签,然后刷新页面。找到那个图片文件,看看Size一栏。如果是从内存或磁盘读的,通常会标成 from memory cache 或 from disk cache,说明根本没走网络请求。
除了缓存,还有别的可能
也不是所有“旧图”都怪缓存。有时候问题出在服务器端。比如用了CDN加速,图片虽然在源站更新了,但CDN节点还没同步,用户访问的是离他近的那个节点,自然看到的是旧版本。
还有一种情况是图片路径被代理或中间层缓存了。比如公司用了Nginx反向代理,默认配置可能会对静态资源缓存几小时。这时候即使浏览器清了缓存,从服务器返回的还是旧文件。
怎么让新图稳稳上线?
最靠谱的办法是在图片链接后面加个版本号。比如把 <img src="/images/photo.jpg"> 改成 <img src="/images/photo.jpg?v=2">。浏览器会认为这是个新地址,必须重新下载。
更自动化一点的做法是用构建工具生成带哈希值的文件名,比如 photo.a1b2c3d.jpg,每次更新文件名都变,彻底避开缓存陷阱。
要是临时救急,也可以让用户强制刷新。Windows上是Ctrl+F5,Mac是Cmd+Shift+R,这样能绕过本地缓存重新拉资源。不过指望普通用户操作不太现实,适合内部测试用。
清缓存不是万能钥匙
很多人一出问题就想着清浏览器历史记录。其实清了之后确实能解决问题,但只是治标。下次访问又可能被缓存住。而且你没法要求所有访客都去清缓存,所以关键还是在发布时就做好版本控制。
顺带提一句,有些网站用标签想禁止缓存,比如:
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
这类标签对HTML页面本身有点用,但对图片、CSS这些外部资源基本无效。真正管缓存的是HTTP响应头,比如服务器返回图片时带上的 Cache-Control: max-age=3600,这才是决定权所在。
所以说,图片加载旧版本,大概率是缓存惹的祸,但到底是浏览器、CDN还是中间代理的问题,得一步步排查。别一上来就让用户清缓存,显得不专业。提前设计好资源更新策略,才能避免每次换图都像在抽奖。