方案思路:比较构建文件的hash值
代码如下:
import { Dialog } from 'vant';
import router from "../router/index"
import Global from '@/utils/global'
// 存储当前脚本标签的哈希值集合
let scriptHashes = new Set();
let timer = undefined;
/**
* 从首页获取脚本标签的哈希值集合
* @returns {Promise<Set<string>>} 返回包含脚本标签的哈希值的集合
*/
console.log(router,'router');
function updateNotice() {
Dialog.alert( {
title: '更新提示',
message: '检测到新版本,请点下方确认按钮以保证正常使用',
}).then(() => {
Global.set('_token',null)
window.location.href = '/'
// window.location.reload()
});
}
async function fetchScriptHashes() {
// 获取首页HTML内容
const html = await fetch('/').then((res) => res.text())
console.log(html);
// 正则表达式匹配所有<script>标签
const scriptRegex = /<script[^>]*>([^<]|<(?!\/script))*<\/script>/gmi;
// const scriptRegex = /<script(?:\s+[^>]*)?>(.*?)</script\s*>/gi;
// 获取匹配到的所有<script>标签内容
const scripts = html.match(scriptRegex) ?? [];
// 将脚本标签内容存入集合并返回
return new Set(scripts);
}
/**
* 比较当前脚本标签的哈希值集合与新获取的集合,检测是否有更新
*/
async function compareScriptHashes() {
// 获取新的脚本标签哈希值集合
const newScriptHashes = await fetchScriptHashes();
console.log(newScriptHashes,'newScriptHashes');
if (scriptHashes.size === 0) {
// 初次运行时,存储当前脚本标签哈希值
scriptHashes = newScriptHashes;
} else if (
scriptHashes.size !== newScriptHashes.size ||
![...scriptHashes].every((hash) => newScriptHashes.has(hash))
) {
// 如果脚本标签数量或内容发生变化,则认为有更新
console.log('更新了', {
oldScript: [...scriptHashes],
newScript: [...newScriptHashes],
});
// 清除定时器
clearInterval(timer);
setTimeout(()=>{
// // 提示用户更新
updateNotice();
},20000)
} else {
// 没有更新
console.log('没更新', {
oldScript: [...scriptHashes],
});
// updateNotice();
}
}
// 每10秒检查一次是否有新的脚本标签更新
timer = setInterval(compareScriptHashes, 20000);
出现的问题:
1、一开始这里用的$router.push("/login") 出问题了,因为路由懒加载,当前线上打包完可能在a.js里,重新打包部署后可能就不在a.js里,就报错了。
2、通知更新的弹窗出的太快了,定时器比如设成20秒,第19秒我在部署,还没部署完,他就弹窗了,此时点击,他就403了,这个时候,就再设置个15秒的定时器,让它15秒后再弹窗。