Vite + Vue3 实现版本更新检查,实现页面自动刷新

前端版本更新检查,实现页面自动刷新

使用 Vite 对 Vue 项目进行打包,对 js 和 css 文件使用了 chunkhash 进行了文件缓存控制,但是项目的 index.html 文件在版本频繁迭代更新时,会存在被浏览器缓存的情况。

在发版后,如果用户不强制刷新页面,浏览器会使用旧的 index.html 文件,在跳转页面时会向服务器端请求了上个版本 chunkhash 的 js 和 css 文件,但此时的文件已经在版本更新时已替换删除了,最终表现为页面卡顿,控制台报错 404。

解决思路

思路 1

服务器端发版时,上一个版本的 assets 内的文件不删除。

缺点是会随着频繁发版,服务器端前端项目文件会越来越多,浪费空间;若旧页面的接口涉及到参数改动等,会引起报错;流水线使用 docker 打包部署会变得非常麻烦。

思路 2

在每次打包生产代码时,在 public 目录下生成一个 version.json 版本信息文件,页面跳转时请求服务器端的 version.json 中的版本号和浏览器本地缓存的版本号进行对比,从而监控版本迭代更新,实现页面自动更新,获取新的 index.html 文件(前提是服务器端对 index.htmlversion.json 不缓存)。

  1. 首先应该禁止浏览器缓存 index.htmlversion.json,这里是 nginx 的不缓存处理的例子

    添加 nginx 配置

    location ~ .*\.(htm|html|json)?$ {
        expires -1;
    }
    
  2. 编写 Vite 插件实现打包时自动生成版本信息

    版本信息插件

    TypeScript 版本,新建文件 src/plugins/versionUpdatePlugin.ts

    // versionUpdatePlugin.ts
    import fs from "node:fs"
    import path from "node:path"
    
    import type { ResolvedConfig } from "vite"
    
    function writeVersion(versionFile: string, content: string) {
      // 写入文件
      fs.writeFile(versionFile, content, (err) => {
        if (err) throw err
      })
    }
    
    export default (version: string | number) => {
      let config: ResolvedConfig
      return {
        name: "version-update",
        configResolved(resolvedConfig: ResolvedConfig) {
          // 存储最终解析的配置
          config = resolvedConfig
        },
        buildStart() {
          // 生成版本信息文件路径
          const file = config.publicDir + path.sep + "version.json"
          // 这里使用编译时间作为版本信息
          const content = JSON.stringify({ version })
          if (fs.existsSync(config.publicDir)) {
            writeVersion(file, content)
          } else {
            fs.mkdir(config.publicDir, (err) => {
              if (err) throw err
              writeVersion(file, content)
            })
          }
        },
      }
    }
    

    JavaScript 版本,新建文件 src/plugins/versionUpdatePlugin.js

    // versionUpdatePlugin.js
    const fs = require("fs")
    const path = require("path")
    
    const writeVersion = (versionFile, content) => {
      // 写入文件
      fs.writeFile(versionFile, content, (err) => {
        if (err) throw err
      })
    }
    
    export default (options) => {
      let config
    
      return {
        name: "version-update",
        configResolved(resolvedConfig) {
          // 存储最终解析的配置
          config = resolvedConfig
        },
        buildStart() {
          // 生成版本信息文件路径
          const file = config.publicDir + path.sep + "version.json"
          // 这里使用编译时间作为版本信息
          const content = JSON.stringify({ version: options.version })
          if (fs.existsSync(config.publicDir)) {
            writeVersion(file, content)
          } else {
            fs.mkdir(config.publicDir, (err) => {
              if (err) throw err
              writeVersion(file, content)
            })
          }
        },
      }
    }
    

    vite 配置文件

    对于使用 TypeScript 的开发者来说,请确保在 env.d.tsvite-env.d.ts 文件中添加类型声明,以获得类型检查以及代码提示。

    // vite-env.d.ts
    declare const __APP_VERSION__: string
    
    // vite.config.js or vite.config.ts
    export default defineConfig((config) => {
      const now = new Date().getTime()
      return {
        // ...
        define: {
          // 定义全局变量
          __APP_VERSION__: now,
        },
        plugins: [
          // ...
          versionUpdatePlugin({
            version: now,
          }),
        ],
        // ...
      }
    })
    
  3. 路由跳转时,实时检测版本

    检测到新版本自动刷新页面,应该使用前置守卫,在跳转失败报错前检测,跳转失败不会触发后置守卫

    const router = useRouter()
    // 这里在路由全局前置守卫中检查版本
    router.beforeEach(async () => {
      await versionCheck()
    })
    
    // 版本监控
    const versionCheck = async () => {
      if (import.meta.env.MODE === "development") return
      const response = await axios.get("version.json")
      if (__APP_VERSION__ !== response.data.version) {
        ElMessage({
          message: "发现新内容,自动更新中...",
          type: "success",
          showClose: true,
          duration: 1500,
          onClose: () => {
            window.location.reload()
          },
        })
      }
    }
    
  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Vue3和Vite实现版本更新自动刷新的方法下: 1. 配置Vite插件:在vite.config.js文件中,可以使用versionUpdatePlugin插件来实现版本更新自动刷新。该插件可以在每次打包生产代码时,在public目录下生成一个version.json版本信息文件,并将版本号定义为全局变量__APP_VERSION__。同时,该插件还可以监控版本迭代更新,并在页面跳转时,通过请求服务器端的version.json文件和浏览器本地缓存的版本号进行对比,从而实现页面自动更新。 ```javascript // vite.config.js import { defineConfig } from 'vite' import versionUpdatePlugin from './versionUpdatePlugin' export default defineConfig((config) => { const now = new Date().getTime() return { define: { __APP_VERSION__: now, // 定义全局变量__APP_VERSION__ }, plugins: [ // 使用versionUpdatePlugin插件 versionUpdatePlugin({ version: now, }), ], // 其他配置项... } }) ``` 2. 创建versionUpdatePlugin插件:在项目根目录下创建一个名为versionUpdatePlugin.js的文件,并在该文件中定义versionUpdatePlugin插件。 ```javascript // versionUpdatePlugin.js export default function versionUpdatePlugin(options) { return { name: 'version-update-plugin', apply: 'build', generateBundle(_, bundle) { const version = options.version const versionInfo = { version: version, } const versionJson = JSON.stringify(versionInfo) // 在public目录下生成version.json文件 this.emitFile({ type: 'asset', fileName: 'version.json', source: versionJson, }) // 其他操作... }, } } ``` 通过以上配置,每次打包生产代码时,会在public目录下生成一个version.json文件,并将版本号定义为全局变量__APP_VERSION__。在页面跳转时,可以通过请求服务器端的version.json文件和浏览器本地缓存的版本号进行对比,从而实现页面自动更新
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值