前端新部署了,如何通知用户刷新网页?

295 阅读1分钟

根据打完包之后生成的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>