怎样主动通知用户更新

米阳 2023-5-17 189 5/17

发现问题

大家实际工作中总会遇到上线了新功能,用户并不能第一时间知道,用户端还是有缓存,除非让用户主动刷新才能更新出新功能,比如测试同学在测试新功能时总是问你“怎么跟原来一样.....”这样的问题,再比如增加了新埋点上线后用户没按照我们预想的调用必经的埋点接口,新用户才行...,等等诸如此类的问题,那今天我们就解决一下这个问题!!!

解决方案

方案1:websocket

涉及到主动通知用户的第一时间就是想到了websocket,大致思路就是新增一个消息通知的长链,后端监听消息数据库如果添加了新的通知,页面上就弹出一个通知框展示更新信息。

优点:复用性强,消息平台搭建好以后除了更新通知其他通知都可配置。

缺点:需要后端配合搭建平台,耗时,占用资源。

方案2:build 时追加文件

1、在build时,生成一个 _version.js 文件,写入当前时间

const fs = require('fs');
const version = Date.now();
const content = `window._version = '${version}';`;
fs.writeFileSync('./_version.js', content);
2、将该文件加入最终生成的 index.html 中
3、去轮询 _version.js 文件,观察远程的 window._version 文件是否和本地不一致
方案2思路我是看了 东风t西瓜 博主的博客他讲的比较细想看这种实现的可以去看看,但是我感觉还是有点复杂了这里既然轮询了文件但是有必要去新创建的一个文件吗,能不能直接轮询整个前端文件进行对照?
我们之请求html入口文件,因为所有的 js 都是通过 script 标签进去的。在这里一定能提取出他们的名字做对比即可。

import { Notification } from '@arco-design/web-react';

export class Updater {
  oldScript: string[] = [];
  intervalId: number | null = null;
  constructor() {
    this.init();
  }
  static async getScriptList() {
    const html = await fetch('/').then((res) => res.text());
    const reg = /<script(?:\s+[^>]*)?>(.*?)</script\s*>/gi;
    const list: string[] = html.match(reg) || []; 
    return list;
  }
  static compare(oldArr: string[], newArr: string[]) {
    const isSame = oldArr.length === newArr.length && oldArr.every((v, i) => v === newArr[i]);
    if (!isSame) {
      Notification.warning({
        id: 'updater',
        title: '更新提示',
        content: '页面有更新,请刷新页面来获取最新功能',
        duration: 30 * 1000,
      });
    }
  }
  async init() {
    const list: string[] = await Updater.getScriptList();
    this.oldScript = list;
  }
  start() {
    const time = 1000 * 60 * 60; // 周期为 1 h 
    this.intervalId = window.setInterval(async () => {
      const list = await Updater.getScriptList();
      Updater.compare(this.oldScript, list);
      this.oldScript = list; // 始终更新缓存 
    }, time);
  }
  stop() {
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }
  }
}

最后把以上文件引入然后调用即可

const updater = new Updater();
updater.start();

 

 

 

- THE END -

米阳

3月17日11:41

最后修改:2025年3月17日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论