背景:对于web项目常常出现的一个问题是:前端有新版本发布了,用户不能及时知晓,导致继续访问了可能有bug的旧版本。 目的:纯前端实现能够主动通知用户更新版本,确保用户能够及时获得最新的功能和修复的 bug。
此方案基本原理:打包的时候生成随机版本号并保存到环境变量里,在index.html的mate标签注入版本号。通过轮询获取index.html的版本号与本地版本号比较。此方案大部分是在前端实现(前提考虑的就是尽量不依赖服务端来实现),服务端要做的仅仅是配置服务器 不缓存index.html。(欢迎评论区交流、分享更多的方案实现~)
以Vue项目为例,具体实现如下:
vue.config.js:
process.env.VUE_APP_VERSION = Date.now() // 生成随机版本号,赋值到环境变量
index.html:
checkForUpdate.js: 开启轮询,定义通知样式
let currentVersion = null
let delay = process.env.VUE_APP_ENV === 'development' ? 6 * 1000 : 10 * 1000
function notifyUserAboutUpdate() {
const updateNotification = document.createElement('div')
updateNotification.innerText = '新版本已发布,请刷新页面以获取最新内容。'
updateNotification.style.position = 'fixed'
updateNotification.style.top = '-45px' // 初始位置在视口上方
updateNotification.style.width = '100%'
updateNotification.style.backgroundColor = 'rgba(248, 215, 218, 0.9)'
updateNotification.style.color = '#721c24'
updateNotification.style.textAlign = 'center'
updateNotification.style.height = '45px'
updateNotification.style.lineHeight = '45px'
updateNotification.style.zIndex = '9999'
updateNotification.style.transition = 'top 1s' // 设置过渡效果
// 定义左右抖动的CSS动画
const styleSheet = document.createElement('style')
styleSheet.type = 'text/css'
styleSheet.innerText = `
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-10px); }
50% { transform: translateX(10px); }
75% { transform: translateX(-10px); }
}
`
document.head.appendChild(styleSheet)
document.body.appendChild(updateNotification)
// 触发从顶部进入效果
setTimeout(() => {
updateNotification.style.top = '0'
}, 500)
// 1.5秒后开始左右抖动动画
setTimeout(() => {
updateNotification.style.animation = 'shake 1s linear infinite'
}, 1500)
// 3.5秒后移除抖动动画
setTimeout(() => {
updateNotification.style.animation = ''
}, 3500)
}
document.addEventListener('DOMContentLoaded', () => {
currentVersion = document
.querySelector('meta[name="version"]')
.getAttribute('content')
if (window.Worker) {
const worker = new Worker('/static/js/updateWorker.js')
worker.postMessage({ currentVersion, delay })
worker.onmessage = (event) => {
if (event.data === 'updateAvailable') {
notifyUserAboutUpdate()
}
}
} else {
console.error('Web Workers are not supported in this browser.')
}
})
updateWorker.js: 定义轮询。此示例使用Worker,避免阻塞主进程。
let currentVersion = null
let delay = null
self.onmessage = (event) => {
currentVersion = event.data.currentVersion
delay = event.data.delay
checkForUpdate()
}
function checkForUpdate() {
fetch('/index.html')
.then((response) => response.text())
.then((html) => {
const versionMatch = html.match(
/
)
if (versionMatch) {
const newVersion = versionMatch[1]
if (newVersion !== currentVersion) {
self.postMessage('updateAvailable')
} else {
setTimeout(() => {
checkForUpdate()
}, delay)
}
} else {
console.error('Version meta tag not found')
}
})
.catch((error) => console.error('Error checking for update:', error))
}
main.js:
import '@/utils/checkForUpdate' // 入口文件引入js
方案二:https://blog.csdn.net/m0_62332650/article/details/143716432