背景
在前端项目部署更新到服务器之后,需要对用户的页面进行更新提示。
原理
- 使用sharedWorker在worker线程中轮询
- 轮询去查看资源是否更新,
etag、last-modified - 如果资源更新,再去判断版本号是否更新。通过接口拿到新的版本号,以及本地缓存代码中的版本号。
- 如果版本号也更新,就弹出更新弹窗。
具体步骤
首先在
sharedWorker中通过轮询去判断服务端资源是否有更新- 轮询就是
setInterval - 判断服务端资源是否更新:通过
HEAD访问/接口,后端接口处理时直接返回index.html文件即可。前端拿到响应头的etag或last-modified- 拿到最新资源标识后,前端通过对比判断资源是否更新
- 如果更新进入下一步版本号的判断
HEAD请求:只返回头部信息,可以减少不必要的网络传输
- 轮询就是
判断版本号
- 前端构建时,需要生成一个版本号,然后将版本号信息写入了
.env文件 以及release.json文件.env文件是为了后面代码中好获取版本号:直接注入环境变量内,通过process.env或者import.meta.env可以方便的获取。release.json文件:一方面是为了后端服务好读取版本号信息,另一方面该文件也能加上版本更新的一些信息,比如哪些模块有更新等。
- 后端接口:提供了一个
/release接口,读取release.json文件,返回当前的版本信息。 - 前端:前端调用接口,由于未刷新用的还是浏览器缓存下来的代码,此时通过对比本地的版本号以及拿到的最新版本信息对比即可
- 如果版本号有更新,弹出更新弹窗
- 前端构建时,需要生成一个版本号,然后将版本号信息写入了
具体代码
这里写了一个极简的demo,可以按照readme.md操作一下。
思考
轮询机制是否有优化空间:需要看业务吧,如果使用websocket,后端服务就需要去监听文件是否变化,本质还是轮询,只是将压力放到了服务端。 如果业务很大,比如上百万的,可能还是轮询好一点,毕竟可以减少服务端压力;当然这样产品的性能就会略差一些。