明天的明天 永远的永远 未知的一切 我与你一起承担 ??

是非成败转头空 青山依旧在 几度夕阳红 。。。
  博客园  :: 首页  :: 管理

背景

当一个页面很久没刷新,又突然点到页面。由于一些文件是因为动态加载的,当重编后(如前后端发版后),这些文件会发生变化,就会出现加载不到的情况。进而导致正在使用的用户,点击页面发现加载不顺畅、卡顿问题。
解决思路

使用Vite构建一个插件,在每次打包时自动生成version.json版本信息文件,记录版本信息(最好使用时间戳来作为版本号)。然后在路由跳转时,通过请求服务端的version.json的版本号与浏览器本地的版本号对比来检测是否需要更新,并弹窗提示用户是否立即刷新页面以获取最新版本。

思路:

在每次打包生产代码时,根据请求服务器端的 version.json 中的版本号和浏览器本地缓存的版本号进行对比来监控版本迭代更新(注意: 要禁止浏览器缓存 index.html 和 version.json!!!

location / {
             #禁止浏览器缓存 index.html 和 version.json
            if ($request_filename ~* .*\.(htm|html|json)$) 
            {
               expires -1;
               #add_header Cache-Control "no-store";
               add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
            }
            client_max_body_size  1024m;
            client_body_buffer_size 1024m; 
            root   "D:\web\front\dist";
            
            try_files $uri $uri/ @router;
            index  index.html index.htm;
            error_page 405 =200 http://$host$request_uri;
        }

 

实现代码

1、在plugins或utils文件夹下新建refreshPlugin.ts文件

import fs from "fs";
import path from "path";
type Version = {
  version: number | string;
};
interface Config {
  publicDir: string;
}

export default ({ version }: Version) => {
  let config: Config = { publicDir: "" };

  return {
    name: "version-plugin", // 必须的,将会在 warning 和 error 中显示
    configResolved(resolvedConfig: Config) {
      // 存储最终解析的配置
      config = resolvedConfig;
    },

    buildStart() {
      // 生成版本信息文件路径
      const file = config.publicDir + path.sep + "version.json";

      // 编译时间作为版本信息
      const content = JSON.stringify({ version });
      writeVersion(file, content);
    },
  };
};

/**
 * 写入文件
 * @param fileName
 * @param version
 */
function writeVersion(
  fileName: string,
  version: string | NodeJS.ArrayBufferView
) {
  fs.writeFile(fileName, version, (err) => {
    if (err) throw err;
  });
}

 

Vite.config.ts配置

// 打包时获取版本信息
import versionPlugin from "../plugins/refreshPlugin";
const timeVersion = new Date().getTime();
 
export default (): UserConfig => {
        const CurrentTimeVersion = new Date().getTime();
 
        return {
            define: {
                // 定义全局变量(转换为时间戳格式)
                'import.meta.env.VITE_APP_VERSION': JSON.stringify(timeVersion),
            },
            plugins: [
                // 版本更新插件
                versionPlugin({
                    version: timeVersion
                })
            ]
        }
    };
});

 

2、utils文件夹下新建versionCheck.ts文件

// 版本检查
import axios from "axios";
import { useMessage } from '@/hooks/web/useMessage';

const { createMessage, createErrorModal } = useMessage();

export const versionCheck = async () => {
  if (import.meta.env.MODE === "development") return;
  const res = await axios.get("version.json");
  
  if (localStorage.getItem('APP_VERSION') != res.data.version) {
    //createErrorModal({ title: '温馨提醒', content: '版本更新提示'});
    localStorage.setItem('APP_VERSION', res.data.version)
   
    // 这里可以根据需求是否弹出询问弹窗还是直接刷新 
    setTimeout(() => {
      window.location.reload();
    }, 2000);
    
  }
};

 

3、路由配置 (检测版本更新的时机)
在路由配置文件(如router/index.ts)中调用检查版本函数

import { versionCheck } from "@/utils/versionCheck";
 
router.beforeEach(async (to, from, next) => {
    // 检查版本
    await versionCheck();
})