• Vue项目如何提示客户端更新新版本?
  • 发布于 2个月前
  • 297 热度
    0 评论
  • 奥特蛋
  • 1 粉丝 43 篇博客
  •   
前言

当我们重新部署前端项目的时候,如果用户一直停留在页面上并未刷新使用,会存在功能使用差异性的问题,因此,当前端部署项目后,需要提醒用户有去重新加载页面。在以往解决方案中,不少人会使用websocket去通知客户端更新,但是为了这么个小功能加入websocket是十分不明智的,新方案的思路是去轮询请求index.html文件,从中解析里面的js文件,由于vue打包后每个js文件都有指纹标识,因此可以对比每次打包后的指纹,分析文件是否存在变动,如果有变动即可提示用户更新。


原理


封装函数 auto-update.js
let lastSrcs; //上一次获取到的script地址
const scriptReg = /<script.*src=["'](?<src>[^"']+)/gm;

async
function extractNewScripts() {
	const html = await fetch('/standard?_timestamp=' + Date.now()).then((resp) = >resp.text());
	scriptReg.lastIndex = 0;
	let result = [];
	let match;
	while ((match = scriptReg.exec(html))) {
		result.push(match.groups.src)
	}
	return result;
}

async
function needUpdate() {
	const newScripts = await extractNewScripts();
	if (!lastSrcs) {
		lastSrcs = newScripts;
		return false;
	}
	let result = false;
	if (lastSrcs.length !== newScripts.length) {
		result = true;
	}
	for (let i = 0; i < lastSrcs.length; i++) {
		if (lastSrcs[i] !== newScripts[i]) {
			result = true;
			break
		}
	}
	lastSrcs = newScripts;
	return result;
}
const DURATION = 5000;

function autoRefresh() {
	setTimeout(async() = >{
		const willUpdate = await needUpdate();
		if (willUpdate) {
			const result = confirm("页面有更新,请刷新查看");
			if (result) {
				location.reload();
			}
		}
		autoRefresh();
	},
	DURATION)
}
autoRefresh();
引入
在main.js中引入
// 引入自动更新提醒
import "@/utils/auto-update.js"
使用element-ui的notify提示更新
修改auto-update.js
let lastSrcs; //上一次获取到的script地址
const scriptReg = /<script.*src=["'](?<src>[^"']+)/gm;

async
function extractNewScripts() {
	const html = await fetch('/standard?_timestamp=' + Date.now()).then((resp) = >resp.text());
	scriptReg.lastIndex = 0;
	let result = [];
	let match;
	while ((match = scriptReg.exec(html))) {
		result.push(match.groups.src)
	}
	return result;
}

async
function needUpdate() {
	const newScripts = await extractNewScripts();
	if (!lastSrcs) {
		lastSrcs = newScripts;
		return false;
	}
	let result = false;
	if (lastSrcs.length !== newScripts.length) {
		result = true;
	}
	for (let i = 0; i < lastSrcs.length; i++) {
		if (lastSrcs[i] !== newScripts[i]) {
			result = true;
			break
		}
	}
	lastSrcs = newScripts;
	return result;
}
const DURATION = 5000;

function autoRefresh() {
	setTimeout(async() = >{
		const willUpdate = await needUpdate();
		if (willUpdate) {
			// 延时更新,防止部署未完成用户就刷新空白
			setTimeout(() = >{
				window.dispatchEvent(new CustomEvent("onmessageUpdate", {
					detail: {
						msg: "页面有更新,是否刷新?",
					},
				}));
			},
			30000);
		}
		autoRefresh();
	},
	DURATION)
}
autoRefresh();
编写模板
CnNotify.vue文件
//堆代码 duidaima.com
<template>
	<div class="cn_notify">
		<div class="content">
			<i class="el-icon-message-solid">
			</i>
			{{ msg }}
		</div>
		<el-row :gutter="20">
			<el-col :span="7" :offset="10">
				<el-button type="primary" @click="onSubmit">
					确定
				</el-button>
			</el-col>
			<el-col :span="7">
				<el-button @click="cancle">
					取消
				</el-button>
			</el-col>
		</el-row>
	</div>
</template>
<script>
	export
default {
		props:
		{
			msg:
			{
				type:
				String,
			default:
				"",
			},
		},
		data() {
			return {};
		},
		created() {},
		methods: {
			// 点击确定更新
			onSubmit() {
				location.reload();
			},
			// 关闭
			cancle() {
				this.$parent.close();
			},
		},
	};
</script>
<style lang='less' scoped>
	.cn_notify { .content { padding: 20px 0; } .footer { display: flex; flex-direction:
	row-reverse; } }
</style>
使用
App.vue
// 引入
import CnNotify from "@common/components/CnNotify.vue";
components: {
  CnNotify,
},
mounted() {
    this.watchUpdate();
},
methods: {
    watchUpdate() {
      window.addEventListener("onmessageUpdate", (res) => {
        let msg = res.detail.msg;
        this.$notify({
          title: "提示",
          duration: 0,
          position: "bottom-right",
          dangerouslyUseHTMLString: true,
          message: this.$createElement("CnNotify", {
            // 使用自定义组件
            ref: "CnNotify",
            props: {
              msg: msg,
            },
          }),
        });
      });
    },
},

用户评论