前端如何检测新版本,并提示用户去刷新
前端如何检测新版本,并提示用户去刷新
先看效果
原理
通过轮询index.html文件的内容来计算文件的哈希值前后是否发生了变化
前端工程化的项目中,以Vue为例,webpack或vite打包通常会构建为很多的js、css文件,每次构建都会根据内容生成唯一的哈希值。如下图所示。
大家可以动手试试,观察一下。
每次构建完index.html中script或link标签引用的地址发生了变化。
代码实现
以Vue+ElementPlus项目为例。在入口文件中引入此文件即可。
// check-version.ts
// 封装了storage,粗暴一点可以用 sessionStorage 代替
import { Storage } from "@/utils/storage";
import { ElLink, ElNotification, ElSpace } from "element-plus";
import { h } from "vue";
import CryptoJS from 'crypto-js';
const storage = new Storage('check-version', sessionStorage);
const APP_VERSION = 'app-version';
let notifyInstance: any;
const generateHash = (text: string): string => CryptoJS.SHA256(text).toString();
const getAppVersionHash = async () => {
const html = await fetch(`${location.origin}?t=${Date.now()}`).then(res => res.text());
const newHash = generateHash(html);
const oldHash = storage.get(APP_VERSION);
return { newHash, oldHash };
}
const checkVersion = async () => {
const { newHash, oldHash } = await getAppVersionHash()
if (oldHash !== newHash) {
if (notifyInstance) return;
notifyInstance = ElNotification({
title: '版本更新',
message: h(ElSpace, null, () => [
h('span', '检测到新版本发布!'),
h(ElLink, { type: 'primary', onClick: () => location.reload() }, () => '立即刷新')
]),
position: 'top-right',
duration: 0,
onClose: () => {
notifyInstance = null
}
})
}
}
const loopCheck = (ms: number) => {
setTimeout(async () => {
await checkVersion()
loopCheck(ms)
}, ms)
}
document.addEventListener('DOMContentLoaded', async () => {
console.log("The DOM is fully loaded and parsed.");
const { newHash } = await getAppVersionHash();
storage.set(APP_VERSION, newHash, null);
loopCheck(1000 * 30);
});
作者:不夏
来源:juejin.cn/post/7519335201505132553
来源:juejin.cn/post/7519335201505132553