Vue多页项目实现在每次版本更新时做提示的解决方案

 更新时间:2025年11月06日 08:42:39   作者:hxmmm  
项目中使用懒加载方式加载组件,在新部署镜像后,由于浏览器缓存又去加载旧的js chunk,但是之时旧的js chunk已经不存在,加载不出来造成bug,所以本文给大家介绍了Vue多页项目实现在每次版本更新时做提示的解决方案,需要的朋友可以参考下

一、遇到的问题

项目中使用懒加载方式加载组件,在新部署镜像后,由于浏览器缓存又去加载旧的js chunk,但是之时旧的js chunk已经不存在,加载不出来造成bug

二、解决方式

在每次部署后更改版本号,在页面做提示,当前版本又更新,提示用户刷新页面

(1)可以使用的方案有哪些

  • 使用轮训查询最新的版本号做对比
  • 使用websocket
  • 使用service worker

(2)最终采用了什么方案

最终使用了方案1;原因是配置简单方便;缺点是会加大服务器压力!~ (1)在public中创建一个version.json文件,写清楚各个模块的版本, 我这里项目vue多页的,每个项目都要单独版本管理

{
"A项目": {
  "version": "1.18.0",
  "description": ""
},
"B项目": {
  "version": "1.18.0",
  "description": ""
},
"C项目": {
  "version": "1.18.0",
  "description": ""
},
}

(2)创建一个全局的versionUpdate方法,来检测版本是否更新

import 'element-plus/dist/index.css'
import { ElMessageBox } from 'element-plus'

/**
 * 版本信息接口
 */
type TVersionInfo = {
  [moduleName: string]: TModuleInfo
}

/**
 * 模块版本存储信息
 */
type TModuleInfo = {
  version: string
  description?: string
}

/**
 * 基于version.json的版本检测和更新提示工具
 */
export class VersionUpdateService {
  private versionCheckInterval: number | null = null
  private readonly CHECK_INTERVAL = 5 * 60 * 1000 // 5分钟检查一次
  private moduleName: string
  private storageKey: string

  constructor(moduleName: string = 'home') {
    this.moduleName = moduleName
    this.storageKey = `module-version-${moduleName}`
  }

  /**
   * 获取模块版本信息
   */
  private getModuleVersionInfo(): TModuleInfo | null {
    const stored = localStorage.getItem(this.storageKey)
    return stored ? JSON.parse(stored) : null
  }

  /**
   * 保存模块版本信息
   */
  private saveModuleVersionInfo(info: TModuleInfo): void {
    localStorage.setItem(this.storageKey, JSON.stringify(info))
  }

  /**
   * 从version.json获取版本信息(统一从 public/version.json 中按模块名读取)
   */
  private async fetchVersionInfo(): Promise<TModuleInfo | null> {
    try {
        const fullUrl = `${window.location.origin}/version.json?t=${Date.now()}`
        console.log(`[${this.moduleName}] 正在获取version.json: ${fullUrl}`)
  
        const response = await fetch(fullUrl, {
            method: 'GET',
            cache: 'no-cache',
            headers: { 'Content-Type': 'application/json' }
        })
  
        if (!response.ok) {
            console.warn(`[${this.moduleName}] 无法获取version.json: ${response.status} ${response.statusText}`)
            return null
        }
  
        // 期望 public/version.json 结构为:{ "A项目": { ... }, "B项目": { ... }, "C项目": { ... }, ... }
        const indexData = await response.json() as TVersionInfo

        console.log(`[${this.moduleName}] 获取到版本信息:`, indexData)
        return indexData[this.moduleName]
    } catch (error) {
        console.warn(`[${this.moduleName}] 获取version.json失败:`, error)
        return null
    }
  }

  /**
   * 检查是否有新版本
   */
  private async checkForUpdate(): Promise<boolean> {
    const currentVersionInfo = await this.fetchVersionInfo()
    if (!currentVersionInfo) {
      console.warn(`[${this.moduleName}] 无法获取当前版本信息,跳过检测`)
      return false
    }
    
    const storedInfo = this.getModuleVersionInfo()
    
    if (!storedInfo) {
      // 第一次检查,保存当前版本信息
      this.saveModuleVersionInfo(currentVersionInfo)
      console.log(`[${this.moduleName}] 首次检查,保存版本信息`)
      return false
    }
    
    const versionUpdated = currentVersionInfo.version !== storedInfo.version
    
    if (versionUpdated) {
      console.log(`[${this.moduleName}] 检测到版本更新:`, currentVersionInfo)
      return true
    }
    
    console.log(`[${this.moduleName}] 当前为最新版本:`, currentVersionInfo)
    return false
  }

  /**
   * 显示更新提示
   */
  private showUpdateNotification(currentVersionInfo: TModuleInfo): void {
    const moduleTitle = this.getModuleTitle(this.moduleName)
    const currentModuleInfo = currentVersionInfo
    const message = `有新版本可用:${currentModuleInfo.version}\n${currentModuleInfo.description}`

    ElMessageBox.confirm(
      message,
      `${moduleTitle}版本更新`,
      {
        confirmButtonText: '立即刷新',
        cancelButtonText: '稍后提醒',
        type: 'info',
        center: true
      }
    ).then(() => {
      this.updateVersionInfo(currentVersionInfo)
      this.reloadPage()
    }).catch(() => {
      console.log(`[${this.moduleName}] 用户选择稍后更新`)
    })
  }

  /**
   * 获取模块标题
   */
  private getModuleTitle(moduleName: string): string {
    const titles: Record<string, string> = {
      'A项目': 'A项目名称'
      ...
    }
    return titles[moduleName] || moduleName
  }

  /**
   * 更新版本信息
   */
  private async updateVersionInfo(currentVersionInfo: TModuleInfo): Promise<void> {
    this.saveModuleVersionInfo(currentVersionInfo)
    console.log(`[${this.moduleName}] 版本信息已更新:`, currentVersionInfo.version)
  }

  /**
   * 刷新页面
   */
  private reloadPage(): void {
    if ('caches' in window) {
      caches.keys().then(names => {
        names.forEach(name => {
          caches.delete(name)
        })
      })
    }
    
    setTimeout(() => {
      window.location.reload()
    }, 100)
  }

  /**
   * 开始定期检查
   */
  public startVersionCheck(): void {
    this.performVersionCheck()
    
    this.versionCheckInterval = window.setInterval(() => {
      this.performVersionCheck()
    }, this.CHECK_INTERVAL)
  }

  /**
   * 执行版本检查
   */
  private async performVersionCheck(): Promise<void> {
    const currentVersionInfo = await this.fetchVersionInfo()
    if (!currentVersionInfo) return
    
    const hasUpdate = await this.checkForUpdate()
    if (hasUpdate) {
      this.showUpdateNotification(currentVersionInfo)
    }
  }

  /**
   * 停止版本检查
   */
  public stopVersionCheck(): void {
    if (this.versionCheckInterval) {
      clearInterval(this.versionCheckInterval)
      this.versionCheckInterval = null
    }
  }

  /**
   * 获取所有模块版本信息(调试用)
   */
  public static getAllModuleVersions(): Record<string, TModuleInfo | null> {
    const modules = ['A项目'...]
    const result: Record<string, TModuleInfo | null> = {}
    
    modules.forEach(module => {
      const key = `module-version-${module}`
      const stored = localStorage.getItem(key)
      result[module] = stored ? JSON.parse(stored) : null
    })
    
    return result
  }

  /**
   * 清除指定模块的版本信息
   */
  public static clearModuleVersion(moduleName: string): void {
    const key = `module-version-${moduleName}`
    localStorage.removeItem(key)
    console.log(`已清除模块 [${moduleName}] 的版本信息`)
  }

  /**
   * 初始化版本更新检测
   */
  public static init(moduleName: string = 'home'): VersionUpdateService {
    const service = new VersionUpdateService(moduleName)
    service.startVersionCheck()
    return service
  }
}

/**
 * 初始化版本更新检测
 */
export const initVersionUpdateJson = (moduleName?: string) => {
  return VersionUpdateService.init(moduleName || 'home')
}

/**
 * 兼容旧版本的导出
 */
export const initVersionUpdate = initVersionUpdateJson

3、在每个模块中的main.ts中引入使用这个方法

import { initVersionUpdateJson } from '@/utils/VersionUpdate'
// 初始化版本检测
initVersionUpdateJson('chess') // 这里传入的是项目名称

到此这篇关于Vue多页项目实现在每次版本更新时做提示的解决方案的文章就介绍到这了,更多相关Vue多页项目版本更新时做提示内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue2.0开发实践总结之入门篇

    vue2.0开发实践总结之入门篇

    这篇文章主要为大家总结了vue2.0开发实践之入门,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • 你知道vue data为什么是一个函数

    你知道vue data为什么是一个函数

    本篇文章从javascript原型链来解释为什么vue中data必须是一个函数,解释一下这部分的原理内容,感兴趣的朋友跟随小编一起看看吧
    2021-11-11
  • vue如何在用户要关闭当前网页时弹出提示的实现

    vue如何在用户要关闭当前网页时弹出提示的实现

    这篇文章主要介绍了vue如何在用户要关闭当前网页时弹出提示的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • vue+elementUI动态增加表单项并添加验证的代码详解

    vue+elementUI动态增加表单项并添加验证的代码详解

    这篇文章主要介绍了vue+elementUI动态增加表单项并添加验证的代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • vue+animation动画实现跑马灯效果

    vue+animation动画实现跑马灯效果

    这篇文章主要为大家详细介绍了vue+animation动画实现跑马灯效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 使用Vue制作图片轮播组件思路详解

    使用Vue制作图片轮播组件思路详解

    这篇文章主要介绍了使用Vue制作图片轮播组件思路详解,需要的朋友可以参考下
    2018-03-03
  • 详解axios在vue中的简单配置与使用

    详解axios在vue中的简单配置与使用

    本篇文章主要介绍了详解axios在vue中的简单配置与使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • vue2中如何使用swiper@5.4.5

    vue2中如何使用swiper@5.4.5

    这篇文章主要介绍了vue2中如何使用swiper@5.4.5问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • vue3中router路由以及vuex的store使用解析

    vue3中router路由以及vuex的store使用解析

    这篇文章主要介绍了vue3中router路由以及vuex的store使用解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 如何在vue中使用HTML 5 拖放API

    如何在vue中使用HTML 5 拖放API

    这篇文章主要介绍了如何在vue中使用HTML 5 拖放API,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下
    2021-01-01

最新评论