Bootstrap

Vite4TSX前端版本号生成

在做基于Vite和React16的项目时,需要前端做版本号管理,当有新版本上线后友好提示客户更新;

1 编写版本号生成插件
  • 根目录新建vite-plugin-version.ts 文件;

新手建议使用buildStart()内封装方法,
如果觉得每次编译后本地也提示版本升级会很麻烦;
就使用closeBundle()但要写死指定目录;

import fs from 'fs';
import path from 'path';
  
export default function vitePluginVersion() { 
  const config = {
    publicDir: ''
  }
  return {  
    name: 'vite-plugin-version', 
    configResolved(resolvedConfig: any) {  
      config.publicDir = resolvedConfig.publicDir
    },
    // 编译前执行回调
    buildStart() {
      /* 大致的意思就是找到存放静态资源的目录,然后新建version.json
        利用编译后静态资源会复制到dist目录下面的逻辑, 来达到目的;
        优点是:灵活,哪怕你是自定义输出目录页也不用担心
        缺点是:每次编译静态文件里面的version.json版本号都会边,也就是每次本地运行都会弹窗要更新版本;
      */
      const file = config.publicDir + path.sep + "version.json";
      const content = JSON.stringify({ version: new Date().getTime() });
			if (fs.existsSync(config.publicDir)) {
        fs.writeFileSync(file,  content, 'utf8');
			} else {
				fs.mkdir(config.publicDir, { recursive: true }, (err: any) => {
          if (err) {
            console.error('创建目录失败:', err);
          } else {
            fs.writeFileSync(file, content, 'utf8');
          }
				});
      }
    }, 
    // 编译后执行回调
    closeBundle() {  
      /*
        这个是编译后的执行回调: 如果在这里使用的话:
        逻辑1:编译完毕后生成一个version.json到,你指定的dist文件夹;如果不自定义输出文件夹,直接写死也不错;
        逻辑2: 加判断,判断静态文件夹是否有version.json文件;如果没有顺便新建一个; 然后单独在dist文件夹输出version.json;
        优点是: 项目已经成功编译了,最后做这件事; 本地静态文件version.json生成一次后续不在重新生成;
        缺点是:每次都要判断静态文件夹是否有, version.json;
      */
      // 创建version.json文件内容  
      // const content = JSON.stringify({ version: new Date().getTime() });
      // 指定输出文件路径第二种方法
      // const outputPath = path.join(process.cwd(), 'dist', 'version.json');  
      // const outputPath = path.resolve(__dirname, 'dist', 'version.json');
      // 写入文件
      // fs.writeFileSync(outputPath,  content, 'utf8');
      // 判断静态文件目录是否存在,不存在就给它生成一个
      // const publicVersionPath = path.join(__dirname, 'public', 'version.json');  
      // if (!fs.existsSync(publicVersionPath)) {
      //   fs.writeFileSync(publicVersionPath, content, 'utf8');
      // };
    }
  };
}
2.使用插件

打开vite.config.ts文件

import vitePluginVersion from './vite-plugin-version'
export default defineConfig({
 plugins: [
 	vitePluginVersion(),
 ]
})
3.编写请求获取版本号方法fetchVersionJson.ts
// 引入第三方localStore存储插件
import storejs from 'storejs';

function fetchBuildVersion() {
    return new Promise((resolve, reject) => {
        fetch('./version.json', {
            cache: 'no-cache', // 禁用缓存
        }).then(response => {
            if (response.status === 404) {
                reject({code: 0, message: `文件找不到`});
                return;
            }
            // 检查响应状态
            if (!response.ok) {
              // 如果响应状态码不是ok,我们认为文件不存在
              reject({code: 0, message: `${response.statusText}`});
              return;
            }
            resolve(response.json());
        }).catch(error => {
            // 网络请求错误处理
            return reject({code: 0, message: '获取version.json时发生错误'});
        });
    });
}
// 最后一次查询时间
let lastFetchTime = 0;
export function HandleGetSoftVersionCode() {
	const currentTime = Date.now();
	// 避免接口密集频繁触发,设置为5秒内只触发1次
    if (currentTime - lastFetchTime < 5000) {
    //   return reject({code: 0, message: '请求太频繁, 5秒内只能请求一次'});
        return;
    }
    lastFetchTime = currentTime;
    // 获取本地版本
    const currLocalVerCode = storejs.get('YYH_Version');
    throttledFetchVersion().then((data: any) => {
        const {version} = data;
        // 表示版本号一致
        if (currLocalVerCode === version) {
            return;
        } else {
            // 版本号不一致, 弹窗提示用户更新
        }
    }).catch((error) => {
        // 表示不是最新版本, 直接提示用户刷新页面获取
        if (error.message === '文件找不到') {
           // 文件找不到, 弹窗提示用户更新
        };
    });
}
4.在Axios全局请求的时候的时候,调用封装方法和本地存储的版本号是否一致;
// 导入获取版本方法
import {HandleGetSoftVersionCode} from './fetchVersionJson';
import axios from "axios";
const service = axios.create({
    timeout: 120 * 1000
});

const request = (config: any) => {
	return new Promise((resolve, reject) => {
		/* 这里可以调用获取版本方法;
		* 还可以排除登陆url,当是登陆的话就不调用获取版本方法;
		* if (config.url !== 'user/login') {};
		*/
		HandleGetSoftVersionCode();
        service(config).then((res) => {
            resolve(res);
        }).catch((err) => {
            reject(err); 
        });
    });
});
export default request;
5.如果不一致就弹窗提示用户更新版本;
// 引入第三方localStore存储插件
import storejs from 'storejs';
// 点击确定存入最新版本,并刷新页面
storejs.set('YYH_Version', '123456789');
location.reload();
;