纯前端实现发版版本变化后页面重新加载
0.原理
- 通过在
前端静态文件目录
下维护一个版本,首次进入页面存储当前版本,轮询
查询静态文件版本是否发生变化,
如果变化则重新加载页面,如果未变化,则继续轮询
1. 优点
- 比通过后端维护在数据库版本进行查询消耗更小,不需要查询数据库,也不用走到后台代码层,只需要访问到ngxin/appache层
- 并且维护纯依靠前端,可控(也可以通过检测/index.html中的js文件hash值,但是
不可控
,如果发版内容不需要页面进行刷新,则无法做到) - 可以结合jekins打包配置,自动进行版本通知
- 可以做到即使用户在同一页面停留很长时间,也能将最新版本代码更新到用户端
缺点:
- 占用请求数量,如果页面请求较多,可能会拖慢进度,可以添加策略处理,请求数量少时再进行处理
- 资源没有合理利用(因为如果不发版则会导致大多数的请求是浪费的)
2.优化
- 为减少请求数量,当浏览器最小化,或不在当前标签内则
停止查询
- 当用户
10min
(可自定义修改时间)内不操作页面(不点击页面),也停止检测,直到操作页面后,继续进行检测,10min内不操作,则停止检测 如果项目使用人数极多,达到
5w以上还可以将轮询改为,当用户点击页面后再进行版本检测
3.代码
1).检测代码
// 检测版本是否有变化 有变化则刷新页面 import version from '../public/assets/version.json'; export default const versionCheck = () => { const checkTime = 5000; // 检测版本请求时间间隔 const clickTime = 5000; // 检测操作时间间隔 每5s检测是否用户超时未操作 const stopDifferTime = 600000; // 停止检测的时间条件 10min 1000 * 60 * 10 10min不操作,则不再检测 window._version = version.version; window.stopVersionCheck = () => {}; window.stopClickCheck = () => {}; async function getVersion() { let res = await fetch(`/assets/config/version.json?random=${Math.random()}`); let { version } = await res.json(); console.log(version, window._version); if (version !== window._version) { window._version = version; return true; } return false; } async function checkNeedReloadPage() { window.stopVersionCheck(); let timer = setInterval(async () => { // 影响查看控制台接口(如果localStorage存在key为timer的值) 直接清楚掉定时器 不检测 if (localStorage.getItem('timer') !== null) { window.stopVersionCheck(); window.stopClickCheck(); } let changeVersion = await getVersion(); if (changeVersion) { console.log('版本发生变化 开始重新加载'); window.location.reload(); } }, checkTime); window._timer = true; // 停止版本检测请求 便于调试 window.stopVersionCheck = () => { window._timer = false; clearInterval(timer); }; } function getSetCurrentTime() { localStorage.setItem('_time', new Date().getTime().toString()); // 操作页面后 如果之前停止了检测 重新启动 !window._timer && checkNeedReloadPage(); } function visibilityChange() { if (document.visibilityState === 'hidden') { window.stopVersionCheck(); window.stopClickCheck(); } else { checkVersion(); } } // 检查是否操作页面 function checkVersion() { // 初始化时间 getSetCurrentTime(); if (localStorage.getItem('_time')) { // 每分钟检测一次 距离上次操作滚动页面时间 超过10分钟未滚动 则停止检测请求 // 注意 小于1s的轮训在页面不可见的情况下(浏览器最小化、切换标签,浏览器会将执行时间固定为1s) let timer = setInterval(() => { let _differTime = new Date().getTime() - Number(localStorage.getItem('_time')); console.log('_differTime', _differTime); if (_differTime > stopDifferTime) { window.stopVersionCheck(); } }, clickTime); window.stopClickCheck = () => { clearInterval(timer); }; } } function addEventListner() { // 检测用户是否点击界面 绑定在document 标签切换也会触发click事件 document.addEventListener('click', getSetCurrentTime); // 如果窗口最小化或者不在当前页签 则不检测 减少请求次数 document.addEventListener('visibilitychange', visibilityChange); } // 初始化 addEventListner(); checkVersion(); };
2).changeVersion.js 发版修改版本脚本
// 用于发版后刷新页面 const fs = require('fs'); const path = require('path'); // 由于pub目录不在rootDir ts报错 pub下供轮训查询使用 const filePathPub = path.resolve(__dirname, '../public/assets/config/version.json'); // 读取 设置新版本 const oldVersion = JSON.parse(fs.readFileSync(filePathPub).toString()); console.log(oldVersion, 'change version before'); const newVersion = JSON.stringify({ version: Math.random() }); console.log(newVersion); fs.writeFileSync(filePathPub, newVersion); console.log(fs.readFileSync(filePathPub).toString(), 'pub 修改后');
3).packge.json script脚本
"publish:version":"node scripts/changeVersion.js && git add . && git commit -m \" 版本发布\" && git push ",
4).version.json
{ "version": 1 }
4. 使用方式
- 将versionCheck 在项目初始化时执行
- 如果需要发布新版本,使页面刷新,则执行脚本yarn(npm run) publish:version
==================================
更合理的方案应该是在路由变化的时候先进行版本检测,可以降低最终消耗,以及让接口请求的消耗在合适的地方
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?