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

背景

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

效果

相关推荐
独隅19 分钟前
前端离线暂停更新策略:Service Worker 与 PWA 的静默控制实践
前端
妙码生花34 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(五十八):后台系统配置管理实现
前端·后端·go
用户938515635071 小时前
React 受控/非受控组件与 React.memo 性能优化——从本质到实战
前端·javascript·react.js
IT_陈寒1 小时前
Java并行流把我坑惨了:原来不是线程安全的!
前端·人工智能·后端
计科土狗1 小时前
GESP六级专题之类与对象
java·前端·数据库
anOnion2 小时前
构建无障碍组件之Listbox Pattern
前端·html·交互设计
凌涘2 小时前
前端路由(三):鉴权、拦截与重定向
前端
半个落月2 小时前
从零梳理 React Router:路由、懒加载、嵌套页面与登录鉴权
前端·react.js
tedcloud1233 小时前
Impeccable 部署指南:开源前端设计工具 Linux 环境搭建实践
linux·运维·服务器·前端·人工智能·开源