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

背景

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

效果

相关推荐
一只小风华~2 分钟前
鸿蒙harmonyOS:笔记 正则表达式
前端·笔记·华为·正则表达式·harmonyos
cg501717 分钟前
“头”里有什么——HTML 元信息
服务器·前端·html
cg501721 分钟前
解析 HTML 网站架构规范
前端·javascript·html
Kx…………29 分钟前
Uni-app入门到精通:subPackages节点为小程序的分包加载配置
前端·学习·小程序·uni-app
齐尹秦1 小时前
HTML5 新的 Input 类型学习笔记
前端·html5
还是鼠鼠2 小时前
Node.js 如何发布一个 NPM 包——详细教程
前端·vscode·npm·node.js
kiro_10232 小时前
【ESP32S3】esp32获取串口数据并通过http上传到前端
前端·网络协议·http
鎏年_4 小时前
Vue2项目打包后,某些图片被转换为base64导致无法显示
前端·javascript·vue.js
小韩本韩!5 小时前
解决electron-builder vue 打包后element-ui字体图标不显示问题
vue.js·ui·electron
康6206 小时前
vue2中引入elementui
前端·javascript·elementui