如果服务端有数据更新,浏览器缓存同时也没有过期,如何直接使用最新的数据
🔹 背景
浏览器缓存分两种:
-
强缓存(强制缓存)
- 由
Cache-Control: max-age=xxx
或Expires
控制。 - 命中强缓存时,且 url 没变,浏览器直接用本地缓存,不会请求服务端。
- 由
-
协商缓存
- 由
ETag / If-None-Match
或Last-Modified / If-Modified-Since
控制。 - 缓存没过期时,浏览器会发请求到服务器确认资源是否有更新。
- 如果没更新,返回
304 Not Modified
。
- 由
👉 问题中的情况:强缓存还没过期,但服务端数据已经更新 → 浏览器还在用旧数据。
🔹 解决方案(实际开发中常用)
1. 改变资源 URL(推荐)
url 不变,且命中强缓存,才会直接使用本地缓存。url 一旦改变,就必须需要请求新的数据。
hash 不是浏览器自己更新的,而是构建工具更新的。
-
文件名加 hash:
构建时给静态资源加版本号,比如:main.js → main.8f3d2c.js
这样每次代码更新,URL 就变了,浏览器一定会重新下载。
-
动态参数:
/api/data?ts=1691234567890 /api/data?version=2
在请求时加上时间戳或版本号,绕过强缓存。
过程说明:
比如第一次构建时生成:
main.abc123.js
浏览器强缓存这个文件后,下一次再请求相同的 URL /static/main.abc123.js,就直接命中缓存,不会再请求服务器。
当你修改了代码并重新构建时,构建工具会生成一个新的文件:
main.xyz789.js
HTML 模板里的引用也会更新为:
<script src="/static/main.xyz789.js"></script>
因为 URL 变了(文件名不同),浏览器会认为这是一个全新的资源,不会命中旧缓存,从而重新请求最新的文件。
👉 所以,hash 是让浏览器去加载“一个新的 URL”,绕过强缓存。旧的 main.abc123.js 即使被强缓存了也没关系,因为 HTML 已经不再引用它。
2. 控制缓存策略
-
关键业务数据(如接口数据):不要走强缓存,改为 协商缓存:
Cache-Control: no-cache
👉 意味着每次都会去服务端确认数据是否更新。
-
静态资源(图片、JS、CSS):走强缓存 + 文件名 hash,保证版本更新时资源刷新。
3. 手动控制请求
-
Ajax/Fetch 请求时,自己加请求头:
fetch('/api/data', {headers: {'Cache-Control': 'no-cache'} })
-
或者在 URL 后拼接时间戳,强制绕过缓存:
fetch(`/api/data?t=${Date.now()}`)
✅ 总结
如果服务端数据更新了,但浏览器强缓存还没过期,浏览器默认还是会用旧数据。
解决办法主要有三种:
- 资源 URL 加 hash 或版本号(构建层面解决,最常用)。
- 调整缓存策略:关键数据用
no-cache
(协商缓存),静态资源走强缓存 + 文件名 hash。 - 请求层面手动绕过缓存:加时间戳参数或请求头。