前端实现自动检测项目部署更新

概述

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

方案

使用轮询的方式请求index.html文件,从中解析里面的js文件,由于工程项目打包后每个js文件都有指纹标识(打包工具自动处理了文件hash,打包后没有需要配置文件hash),因此对比每次打包后的指纹,分析文件是否存在变动,如果有变动则提示用户更新,流程如下:

实现

新建auto-update.ts,内容如下

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

// 上一次获取到的script地址列表,用于比较是否有更新
let initScriptSrcList: string[] = [];

// 正则表达式用于匹配HTML中的script标签的src属性
const scriptReg = /<script.*src=["'](?<src>[^"']+)/gm;

/**
 * 从当前页面HTML中提取所有script标签的src地址
 * @returns {Promise<string[]>} 返回包含所有script src的数组
 */
const extractNewScripts = async () => {
    // 添加时间戳参数避免缓存
    const param = Date.now()
    // 获取当前页面HTML内容
    const html = await fetch('/?_time=' + param).then((resp) => resp.text());
    
    // 重置正则表达式匹配位置
    scriptReg.lastIndex = 0;
    let result = [];
    let match: RegExpExecArray
    
    // 遍历匹配所有script标签的src属性
    while ((match = scriptReg.exec(html) as RegExpExecArray) {
        result.push(match.groups?.src)
    }
    return result;
}

/**
 * 检查是否有新的脚本更新
 * @returns {Promise<boolean>} 返回true表示有更新,false表示无更新
 */
const isUpdate = async () => {
    // 获取当前页面所有script的src
    const newScripts: string[] = await extractNewScripts();
    
    // 如果是第一次检查,初始化脚本列表并返回无更新
    if (!initScriptSrcList.length) {
        initScriptSrcList = newScripts;
        return false;
    }
    
    let res = false;
    
    // 比较脚本数量是否有变化
    if (initScriptSrcList.length !== newScripts.length) {
        res = true;
    }
    
    // 逐个比较脚本地址是否有变化
    for (let i = 0; i < initScriptSrcList.length; i++) {
        if (initScriptSrcList[i] !== newScripts[i]) {
            res = true;
            break
        }
    }
    
    // 更新初始脚本列表为当前最新
    initScriptSrcList = newScripts;
    return res;
}

// 检查间隔时间(5秒)
const DELAY_TIME = 5000;

/**
 * 自动刷新功能入口
 * 每隔指定时间检查一次脚本更新,有更新时提示用户刷新页面
 */
export const autoRefresh = () => {
    setTimeout(async () => {
        // 检查是否需要更新
        const needUpdate = await isUpdate();
        
        if (needUpdate) {
            console.log('检测到页面有内容更新,自动刷新');
            
            // 使用Element Plus的MessageBox提示用户
            ElMessageBox.confirm('检测到页面有内容更新,是否立即刷新?', '更新提示', {
                confirmButtonText: '确认',
                showCancelButton: false,  // 不显示取消按钮
                type: 'warning'          // 警告类型提示框
            }).then(() => {
                // 用户确认后刷新页面
                location.reload();
            })
        }
        
        // 递归调用自身,实现持续检查
        autoRefresh();
    }, DELAY_TIME)
}

使用

我这里使用的是vite+vue的形式,在app.vue文件中

js 复制代码
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
import { onMounted } from "vue";
import { autoRefresh } from "./utils/auto-update";

onMounted(() => {
//生产环境开启检测
  if (import.meta.env.MODE == "production") {
    autoRefresh();
  }
});
</script>
相关推荐
oil欧哟2 分钟前
🧐 我用 Vibe Coding 从 0 到 1 打造 AI 产品,上线一个月效果如何?有什么心得?
前端·产品·vibecoding
霍克itxt点top10 分钟前
NestJS 入门到实战 前端必学服务端新趋势无密分享
前端
xiguolangzi10 分钟前
1panel web服务部署
前端
摘星编程14 分钟前
Cursor Pair Programming:在前端项目里用 AI 快速迭代 UI 组件
前端·人工智能·ui·typescript·前端开发·cursorai
醉方休1 小时前
React Fiber 风格任务调度库
前端·javascript·react.js
北辰alk1 小时前
React Intl 全方位解析:为你的 React 应用注入国际化灵魂
前端
李白白i单身版1 小时前
前端VUE项目实现静默打印,无需用户手动确认
前端
bysking1 小时前
【29 - git bisect】git bisect 命令进行二分定位,排查异常commit bysking
前端
华仔啊1 小时前
摸鱼神器!前端大佬私藏的 11 个 JS 神级 API,复制粘贴就能用,效率翻倍
前端·javascript
一枚前端小能手1 小时前
🔥 React Hooks又让我重新渲染了999次!这些坑你踩过几个?
前端