2022年React应用每次部署后如何自动强制刷新浏览器缓存
2022年Create React App 部署后自动更新缓存最佳实践
直接给生产环境验证过的落地路径,从改造成本最低的方案开始说,没有冗余设计。
零代码改造成熟方案(覆盖90%普通业务场景)
绝大多数人遇到的缓存不更新问题,根本不是React本身的问题,是服务端缓存头配错了。
CRA从react-scripts 4.x版本开始,默认构建产出的静态资源(static/js、static/css、static/media目录下的文件)文件名都自带内容hash,只要文件内容有改动,构建出来的文件名hash就会完全变化,天然做了缓存隔离。你只需要给部署服务配两类缓存规则就行,不用改一行前端代码:
- 对所有带hash的静态资源,响应头设置
Cache-Control: public, max-age=31536000, immutable,这类文件内容变了文件名就变,缓存多久都不会冲突,还能最大化利用浏览器缓存提升加载速度。 - 对站点入口
index.html、favicon.ico、manifest.json这类构建后文件名固定、不带hash的文件,响应头设置Cache-Control: no-cache,这个配置不是说不缓存,是每次请求都会先去服务端校验文件是否有更新,有更新就拉新版本,没更新就直接用本地缓存,兼顾更新及时性和加载速度。
实踩过的坑:至少8成的缓存不更新问题,都是部署配置时给
index.html也加了十天半个月的长缓存,浏览器根本不会去拉新的入口文件,自然永远加载旧的资源包,把这个规则改完基本就解决问题了。
进阶方案(适配长时间打开的应用场景)
如果你的产品是后台系统、数据大屏这类用户可能连续开着好几天不关闭的应用,光配缓存头还不够——用户第一次打开页面时加载的是旧版本的资源包,只要不手动刷新,哪怕后台已经部署了新版本,页面也不会自动更新。这种场景加个轻量的版本检测就行,代码量不超过20行,不用引任何第三方库:
- 在项目
public目录下新建version.json文件,内容只需要存一个版本标识就行,比如可以是构建时间戳、git commit hash,示例:{"version": "202209161530"},可以写个简单的构建脚本每次打包的时候自动更新这个值,不用手动改。 - 在项目根组件(一般是
App.js)的入口逻辑里,存一下首次加载时拿到的version值,然后加个定时轮询(比如每5分钟请求一次version.json,请求的时候加个随机参数避免被本地缓存拦截),把新拿到的version和本地存的初始值做对比:- 如果值不一致,说明后台已经部署了新版本,可以弹个轻量提示告知用户“应用已发布新版本,点击刷新获取最新功能”,用户确认后调用
window.location.reload()触发刷新即可。 - 要做无感刷新也可以,注意避开用户正在填写表单、操作未保存的场景就行,避免打断用户操作。
- 如果值不一致,说明后台已经部署了新版本,可以弹个轻量提示告知用户“应用已发布新版本,点击刷新获取最新功能”,用户确认后调用
注意:
version.json的缓存规则和index.html保持一致,设置Cache-Control: no-cache,不然拉到的永远是旧版本的标识文件,检测逻辑就失效了。
几个别碰的过时/踩坑方案
- 别图省事给整个站点配
Cache-Control: no-store,等于完全关掉浏览器缓存,首屏加载速度会掉30%以上,纯纯浪费性能。 - 别在请求静态资源的时候统一加时间戳破缓存,直接废掉CRA自带的hash缓存优化,平白浪费带宽。
- 对PWA/Service Worker不熟悉的话,别随便开CRA默认生成的serviceWorker注册逻辑,Workbox的缓存更新逻辑没配好很容易出现“硬刷新都刷不出新版本”的死缓存问题,普通业务场景直接保持
serviceWorker.unregister()就够了。
内容的提问来源于stack exchange,提问作者Kelden Mayer
相关产品推荐
相关产品推荐

