React 前端导航

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

前端重新部署后如何通知在线用户刷新网页加载最新代码

背景

版本发布上线后,如果用户还停留在老页面,此时用户并不知道网页已经重新部署了,跳转页面的时候可能会出 js 链接 的hash变了导致报错跳不过去的情况,前端需要保证用户的最佳体验。

探讨解决思路

如果后端可以配合前端的话,前端可以使用 webSocket 跟后端实时通讯,前端部署发布完成后,后端发个消息通知,前端检测到 Message 就进行更新提示,或者使用 EventSource, 这跟 webSocket 很像,只不过 EventSource 只能后端推送消息到前端,前端发送消息给后端,当前场景中前端也发送消息给后端。

以上方案需要有后端参与配合,但是当前后台同学腾不出时间来配合实现,所以需要找一个纯前端的解决方案。

以下是我们讨论后得出的两种方案:

  • 1.在项目根目录放一个 json 文件,写入一个固定的key值然后打包的时候变一下,然后代码中轮询去判断看有没有变化,如果有的话就提示更新。但是写完之后发现太麻烦了,需要手动配置json文件,还需要打包的时候修改。

  • 2.第二种方案是根据打完包之后生成的script src 的hash值去判断,每次打包都会生成唯一的hash值,只要轮询去判断不一样了,那一定是重新部署了.

方案2实现

interface Options {
    time?: number
}

export class Updater {
    oldScripts: string[] //保存当前 script 的 hash 数据
    newScripts: string[] //保存最新 script 的 hash 数据
    dispatcher: Record<string, Function[]> //发布订阅,通知用户有更新
    
    constructor(options: Options) {
        this.oldScripts = [];
        this.newScripts = []
        this.dispatcher = {}
        this.init() //初始化
        this.timing(options?.time)//轮询
    }


    async init() {
        const html: string = await this.getHtml()
        this.oldScripts = this.parserScript(html)
    }

    //读取index html
    async getHtml() {
        const html = await fetch('/').then(res => res.text());
        return html
    }

    //解析 script 标签
    parserScript(html: string) {
        const reg = new RegExp(/<script(?:\s+[^>]*)?>(.*?)<\/script\s*>/ig) //script正则
        return html.match(reg) as string[] //匹配script标签
    }

    //发布订阅通知
    on(key: 'noUpdate' | 'update', fn: Function) {
        if(!this.dispatcher[key]){
            this.dispatcher[key] = [];
        }
        this.dispatcher[key].push(fn)  
        return this;
    }

    compare(oldArr: string[], newArr: string[]) {
        const base = oldArr.length
        const arr = Array.from(new Set(oldArr.concat(newArr)))
        //新旧 length 一样就是没有更新
        if (arr.length === base) {
            this.dispatcher['noUpdate'].forEach(fn => {
                fn();
            });
        
        }
        //否则通知更新
        else {
            this.dispatcher['update'].forEach(fn => {
                fn();
            });
        }
    }

    timing(time = 15000) {
         //轮询
        setInterval(async () => {
            const newHtml = await this.getHtml()
            this.newScripts = this.parserScript(newHtml)
            this.compare(this.oldScripts, this.newScripts)
        }, time)
    }

}

如何使用 Updater 类

//实例化该类
const up = new Updater({
    time:2000
})
//未更新通知
up.on('noUpdate',()=>{
   console.log('没有更新'); 
})
//更新通知
up.on('update',()=>{
    console.log('有更新');
    location.reload();// 重新加载页面
})

测试一下

  • 执行 npm run build 第一次打包
  • 安装 http-server
  • 使用 http-server 启动服务
  • 访问应用并停留
  • 重新执行 npm run build 再次打包
  • 查看浏览器日志打印情况

这样子就可以检测出来有没有重新发布就可以通知用户更新了。

声明:本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。邮箱:farmerlzj@163.com。 本站原创内容未经允许不得转载,或转载时需注明出处: 内容转载自: React前端网:https://qianduan.shop/blogs/detail/74

#js#前端部署

相关推荐

原型与原型链、继承

原型与原型链、继承简单实现

浏览器中的js事件循环(Event loop)

本文将简述浏览器中的js事件循环机制,帮助我们理解浏览器环境js代码是如何运行的。Javascript的一大特点是单线程,也就意味着同一时间他只能做一件事。事件循环(Event Loop)是为了协调事件,用户交互,UI渲染,网络处理等行为,防止线程阻塞而诞生的。