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

背景

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

效果

相关推荐
前端小趴菜0520 分钟前
React - 组件通信
前端·react.js·前端框架
Amy_cx40 分钟前
在表单输入框按回车页面刷新的问题
前端·elementui
dancing9991 小时前
cocos3.X的oops框架oops-plugin-excel-to-json改进兼容多表单导出功能
前端·javascript·typescript·游戏程序
后海 0_o1 小时前
2025前端微服务 - 无界 的实战应用
前端·微服务·架构
Scabbards_1 小时前
CPT304-2425-S2-Software Engineering II
前端
小满zs1 小时前
Zustand 第二章(状态处理)
前端·react.js
程序猿小D2 小时前
第16节 Node.js 文件系统
linux·服务器·前端·node.js·编辑器·vim
萌萌哒草头将军2 小时前
🚀🚀🚀Prisma 发布无 Rust 引擎预览版,安装和使用更轻量;支持任何 ORM 连接引擎;支持自动备份...
前端·javascript·vue.js
狼性书生2 小时前
uniapp实现的简约美观的星级评分组件
前端·uni-app·vue·组件
书语时2 小时前
ES6 Promise 状态机
前端·javascript·es6