vue 版本更新,用户未刷新导致页面白屏的解决方法
方法一:本地轮询查询 index.html 的 js 文件携带的 hash/时间戳 数据
export class Updater {
timerId = null
constructor(options) {
this.oldScript = []
this.newScript = []
this.dispatch = {}
this.init()
this.timing(options?.timer)
}
async init() {
const html = await this.getHtml()
this.oldScript = this.parserScript(html)
}
async getHtml() {
const html = await fetch('/').then((res) => res.text())
return html
}
parserScript(html) {
const reg = new RegExp(/<script(?:\s+[^>]*)?>(.*?)<\/script\s*>/gi)
return html.match(reg)
}
on(key, fn) {
;(this.dispatch[key] || (this.dispatch[key] = [])).push(fn)
return this
}
compare(oldArr, newArr) {
const base = oldArr.length
const arr = Array.from(new Set(oldArr.concat(newArr)))
if (arr.length === base) {
;(this.dispatch['no-update'] || []).forEach((fn) => {
fn()
})
} else {
;(this.dispatch['update'] || []).forEach((fn) => {
fn()
})
}
}
timing(time = 10000) {
if (process.env.NODE_ENV === 'development') return
this.timerId = setInterval(async () => {
const newHtml = await this.getHtml()
this.newScript = this.parserScript(newHtml)
this.compare(this.oldScript, this.newScript)
}, time)
}
start() {
this.timing()
}
stop() {
this.timerId && clearInterval(this.timerId)
}
}
export const up = new Updater({
timer: 5000,
})
export function noUpdateFun(callBack) {
up.on('no-update', () => {
typeof callBack === 'function' && callBack.call(this)
})
}
export function updateFun(callBack) {
up.on('update', () => {
typeof callBack === 'function' && callBack.call(this)
})
}
方法2:nginx 配置 index.html 不缓存
- 注意只配置 index.html 不缓存,如果都不缓存,每次刷新都全部重新请求,不如使用方法一的轮询,消耗还小一些
配置nginx的html不缓存并重启nginx
vim nginx.cong
将以下内容写入并 :wq 保存
location / {
root web/;
index index.html;
try_files $uri $uri/ /index.html;
# add_header Cache-Control "no-cache, no-store";
# 控制版本更新缓存 - 不推荐,导致所有文件不被缓存
# add_header Cache-Control "no-cache, no-store, must-revalidate";
# add_header Pragma "no-cache";
# add_header Expires 0;
#以下配置解决html不缓存,也可以配置css和js分别缓存7天和30天。这里未配置
if ($request_filename ~* .*\.(?:htm|html)$)
{
add_header Cache-Control "private, no-store, no-cache";
}
}
- 重启nginx
- 进入 /usr/local/nginx/sbin 路径,会存在一个 nginx 的文件
./nginx -s reload
如果以上未生效,可能是进程导致,需要停用再启动
- 查询所有nginx的进程
- 会获取一个进程的 pid
ps aux | grep nginx
- 根据 pid 查询进程监听 端口号,找到控制 80端口的pid
netstat -anp | grep {pid}
kill {pid}
或者
kill -9 {pid}
- 重新启动进程,执行nginx即可
- 进入 /usr/local/nginx/sbin 路径,会存在一个 nginx 的文件
./nginx