前端如何实现自动检测更新

背景

用户在访问单页面网站时,如果生产环境已经发布了新的版本(有功能上的变化),由于单页面中路由特性或浏览器缓存的原因,并不会重新加载前端资源,此时用户浏览器所并非加载是最新的代码,从而可能遇到一些 bug。

部署之后,如何提醒用户版本更新,并引导用户刷新页面呢?

方案

这里用的【轮询】的方式请求index.html文件,从中解析里面的js文件,由于vue打包后每个js文件都有指纹标识,因此对比每次打包后的指纹,分析文件是否存在变动,如果有变动则提示用户更新!

环境:vue3 + ts + vite + element-plus

步骤

1.在utils文件夹下新建auto-update.ts,内容如下

typescript 复制代码
import { ElMessageBox } from 'element-plus'


let lastSrcs: any;  //上一次获取到的script地址
let needTip = true; // 默认开启提示

const scriptReg = /<script.*src=["'](?<src>[^"']+)/gm;

const extractNewScripts = async () => {
    const html = await fetch('/?_timestamp=' + Date.now()).then((resp) => resp.text());
    scriptReg.lastIndex = 0;
    let result = [];
    let match: RegExpExecArray
    while ((match = scriptReg.exec(html) as RegExpExecArray)) {
        result.push(match.groups?.src)
    }
    return result;
}

const needUpdate = async () => {
    const newScripts = await extractNewScripts();
    if (!lastSrcs) {
        lastSrcs = newScripts;
        return false;
    }
    let result = false;
    if (lastSrcs.length !== newScripts.length) {
        result = true;
    }
    for (let i = 0; i < lastSrcs.length; i++) {
        if (lastSrcs[i] !== newScripts[i]) {
            result = true;
            break
        }
    }
    lastSrcs = newScripts;
    return result;
}
const DURATION = 10000;

export const autoRefresh = () => {
    setTimeout(async () => {
        const willUpdate = await needUpdate();
        if (willUpdate) {
            // 延时更新,防止部署未完成用户就刷新空白
            setTimeout(() => {
                ElMessageBox.confirm('检测到页面有内容更新,为了功能的正常使用,是否立即刷新?', '更新提示', {
                    confirmButtonText: '确认',
                    showCancelButton: false,
                    type: 'warning'
                }).then(() => {
                    location.reload();
                })
            }, 30000);
            needTip = false; // 关闭更新提示,防止重复提醒
        }
        if (needTip) {
            autoRefresh();
        }
    }, DURATION)
}
  1. Vite的相关配置
javascript 复制代码
/** 
 * @description vite document address
 * https://vitejs.cn/config/ 
 */
export default xxx = () => {
  return {
    base: './',
    resolve: {
      ...
    },
    server: {
      ...
    },
    build: {
      rollupOptions: {
        output: {
          chunkFileNames: 'js/[hash].js', // 引入文件名的名称
          entryFileNames: 'js/[hash].js', // 包的入口文件名称
          assetFileNames: '[ext]/[hash].[ext]', // 资源文件像 字体,图片等
        }
      }
    }
  }
}
  1. 在入口文件mati.ts中引入autoRefresh,如果是生产环境,则执行autoRefresh方法。
javascript 复制代码
import { autoRefresh } from "@/utils/auto-update"
if (import.meta.env.MODE == 'production') {
  autoRefresh()
}

效果

相关推荐
技术钱13 分钟前
react antdesign实现表格嵌套表单
前端·react.js·前端框架
小p23 分钟前
react学习4:CSS Modules 样式
前端·react.js
东华帝君26 分钟前
小型列表是否需要拆分成服务器组件
前端
卍郝凝卍27 分钟前
物联网卡摄像头从前端至后台的实现过程
前端·物联网·视频解决方案
疯狂暴龙GG帝28 分钟前
项目中使用el-table实现行合并及合并后序号不连续解决方案
前端·vue.js
东华帝君30 分钟前
React Hook Form —— useForm 和 FormProvider+useFormContext
前端
胖虎26538 分钟前
用 Three.js 打造炫酷波浪粒子背景动画:从原理到实现
vue.js·动效
小p40 分钟前
react学习3: 闭包陷阱
前端·react.js
该用户已不存在1 小时前
Vibe Coding 入门指南:从想法到产品的完整路径
前端·人工智能·后端
Pedro1 小时前
Flutter - 日志不再裸奔:pd_log 让打印有型、写盘有序
前端·flutter