根据打完包之后生成的script src 的hash值去判断,每次打包都会生成唯一的hash值,只要轮询去判断不一样了,那一定是重新部署了.
本文以vue项目为例
如下index.html: 可看到build后的script的hash
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
<script type="module" crossorigin src="/assets/index-1f400fzz.js"></script>
<link rel="stylesheet" href="/assets/index-59824eff.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
update.js
export class Updater {
constructor(options) {
this.oldScript = [];
this.newScript = []
this.dispatch = {}
this.init() //初始化
this.timing(options?.timer)//轮询
}
async init() {
const html = await this.getHtml()
this.oldScript = this.parserScript(html)
}
async getHtml() {
const html = await fetch('/').then(res => res.text());//读取index html
return html
}
parserScript(html) {
const reg = new RegExp(/<script(?:\s+[^>]*)?>(.*?)<\/script\s*>/ig) //script正则
return html.match(reg) //匹配script标签
}
//发布订阅通知
on(key, fn) {
if (this.dispatch[key] || (this.dispatch[key] = [])) this.dispatch[key].push(fn)
return this;
}
compare(oldArr, newArr) {
const base = oldArr.length
const arr = Array.from(new Set(oldArr.concat(newArr)))
//如果新旧length 一样无更新
if (arr.length === base) {
this.dispatch['no-update'].forEach(fn => {
fn()
})
} else {
//否则通知更新
this.dispatch['update'].forEach(fn => {
fn()
})
}
}
timing(time = 10000) {
//轮询
setInterval(async () => {
const newHtml = await this.getHtml()
this.newScript = this.parserScript(newHtml)
this.compare(this.oldScript, this.newScript)
}, time)
}
}
使用update.js到App.vue中
<script setup>
import { Updater } from "./update";
//实例化该类
const up = new Updater({
timer: 2000,
});
//未更新通知
up.on("no-update", () => {
console.log("未更新");
});
//更新通知
up.on("update", () => {
console.log("更新了");
});
</script>