vue.config.js配置项
configureWebpack: config => {
...
config.output.filename = `static/js/[name].${Date.now()}.js`
config.output.chunkFilename = `static/js/buildVersion/[name].${Date.now()}.js`
...
return {
name,
resolve: {
alias: {
'@': resolve('src')
}
}
}
}
校验静态资源加载错误
function handleListenerError(eventErr) {
if (eventErr.filename.indexOf('buildVersion') > -1) {
showNotification()
}
eventErr.preventDefault()
}
function listenerError() {
window.addEventListener('error', debounce(handleListenerError), true)
}
listenerError()
控制台输入以下内容后回车:
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = '/static/js/buildVersion/non-existent-file.js'; // 不存在的路径
document.head.appendChild(script); // 添加到 DOM 中触发加载
version-upgrade.js
import { Notification } from 'element-ui'
const LOOPER_TIME = 1000 * 30 // 检测版本更新的轮训时间
let preTag = '' // 用于记录初次进入网站或网站被刷新时的Etag信息
let timeoutId = null
export const checkForUpdates = async () => {
const curTag = await getTag()
console.log('preTag', preTag, timeoutId)
console.log('curTag', curTag, timeoutId)
if (preTag !== curTag) {
showNotification()
if (timeoutId) {
clearTimeout(timeoutId)
timeoutId = null
}
} else {
timeoutId = setTimeout(checkForUpdates, LOOPER_TIME) // 重新设置定时器
}
}
const init = async () => {
preTag = await getTag()
console.log('初始化-preTag', preTag)
if (timeoutId) {
clearTimeout(timeoutId)
timeoutId = null
}
// timeoutId = setTimeout(checkForUpdates, LOOPER_TIME) // 初次设置定时器
}
init()
/**
* 检测到版本更新后,notification会一直显示在页面上
*/
const showNotification = () => {
Notification.closeAll()
Notification({
duration: 0,
title: '版本更新提示',
dangerouslyUseHTMLString: true,
message:
"检测到有新版本发布,请<a href='javascript:location.reload()' style='color: green'>刷新</a>页面",
})
}
/**
* 获取网站资源的Etag信息
*
* @returns 网站资源的Etag信息
*/
async function getTag() {
const response = await fetch(window.location.origin, {
method: 'HEAD', // 用于获取资源的元数据,与GET请求类似,HEAD请求也像服务器发送请求,但服务器只需要回传资源的头部信息,不需要回传资源的实体主体。
cache: 'no-cache'
})
return response.headers.get('Etag')
}
// 监听错误
const debounce = (fn, delay = 200) => {
let timer = null
return (...args) => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn(...args)
}, delay)
}
}
function handleListenerError(eventErr) {
console.log('监听到静态资源加载错误', eventErr)
if (eventErr.filename.indexOf('buildVersion') > -1) {
showNotification()
}
eventErr.preventDefault()
}
function listenerError() {
window.addEventListener('error', debounce(handleListenerError), true)
}
listenerError()
main.js中导入
import './version-upgrade' // 发布版本提示用户刷新
路由切换时触发检测
路由守卫中使用:
import { checkForUpdates } from './utils/version-upgrade'
...
router.afterEach(() => {
checkForUpdates()
})