项目技术栈:vue3 + ant design vue + ts + vite
版本号如何加?我的做法是在打包的时候,用当前打包时间作为版本的唯一标识。
- 首先封装一个vite的plugin,功能是在打包/构建时动态写入版本号。在根目录新建
myPlugins/buildLifeHooks。内容如下:
import fs from 'fs';
import path from 'path';
// 在Vite配置中添加一个插件,监听build事件
export function buildLifeHook() {
return {
name: 'build-life-hook',
buildStart(){
let now = new Date().toLocaleString().replace(/\//g,'-')
let version = {
version:now,
}
let versionPath = path.join(__dirname,'../public/version/versionData.json');
fs.writeFile(versionPath,JSON.stringify(version),'utf8',(err)=>{
if(err){
console.log('写入文件失败');
}else{
console.log('写入文件成功');
}
})
console.log('构建开始!' + now);
},
buildEnd() {
let now = new Date().toLocaleString().replace(/\//g,'-')
console.log('构建完成!' + now);
},
};
}
在vite.config.ts中导入:
import { buildLifeHook } from './myPlugins/buildLifeHook';
...
defineConfig({
...
plugins:[buildLifeHook()],
})
此时版本号文件就生成了,并且每次打包后这个文件的内容都不一样。
下一步就是监听新版本发布。
- 我的思路是通过轮询获取线上json,之后与本地的版本记录相比,如果相同则什么也不做,如果不同,则弹窗通知用户更新版本,确认更新后,刷新页面即可获取新版本。
- 当然用户如果正在操作系统,不方便更新,也可以选择暂时忽略更新,此时清除轮询,等待用户后续手动刷新页面即可。
- 接下来是代码实现:在utils文件夹下新建
checkVersions.ts文件。内容如下:
import { Modal } from 'ant-design-vue'
/**
* @description 检测版本更新
* @param allowIgnore 是否允许忽略
* @param timer 传入定时器
* @returns
*/
export async function checkUpdate(allowIgnore:boolean, timer?:any) {
//动态获取线上的资源地址,其实就是vite.config.ts的base的值
let basePath = import.meta.env.VITE_PUBLIC_PATH
try {
// 检测前端资源是否有更新
let response = await fetch(`${basePath}/version/versionData.json`,{
headers: {
'Cache-Control': 'no-cache'
}
}).then(res => res.json())
if(!localStorage.getItem('v3_version')){
localStorage.setItem('v3_version',response.version)
}else{
if(localStorage.getItem('v3_version')!==response.version){
Modal.destroyAll()
Modal.confirm({
title: '检测到新版本',
content: '是否立即更新?',
okText: '更新',
cancelText: '忽略',
cancelButtonProps:{
// 是否禁用
disabled:!allowIgnore
},
onOk: () => {
localStorage.setItem('v3_version',response.version)
window.location.reload()
},
onCancel: () => {
if(timer!=null && timer!==undefined){
clearInterval(timer)
}
}
})
}
}
} catch (e) {
return Promise.reject(e)
}
}
/**
* @description 初始化版本检测器
*/
export function initVersionCheck(){
// checkUpdate(false)
let timer = setInterval(()=>{
checkUpdate(true,timer)
},60000)
}
轮询间隔我设置的1分钟。读者可以按照实际情况调整。
在APP.vue中引入该文件:
import { initVersionCheck } from '@/utils/checkVersion'
import { computed, onMounted, ref } from 'vue';
...
onMounted(() => {
initVersionCheck()
})
之后就可以正常检测版本更新啦。
这只是一种简单的版本更新检测方法,一定还有很多其他的实现方式,后续有时间我会再更新,也欢迎读者一起探讨。
2024-06-02更新。
fetch请求的时候,添加如下配置:已在上文中加上,目的是解决浏览器缓存机制可能的导致问题。
headers: {
'Cache-Control': 'no-cache'
}
- 关于请求时机的说明:轮询或者放在路由守卫中都是可以的,因为加版本号、检查更新的
checkUpdate函数,初始化更新检查的initVersionCheck,这三个方法的逻辑是分开写的,所以读者可以灵活运用,按照自己需要调整即可。