前端项目部署自动检测更新后通知用户刷新页面(前端实现,技术框架vue、js、webpack)——方案一:编译项目时动态生成一个记录版本号的文件

金乌Y 2024-06-24 16:03:02 阅读 60

前言

当我们重新部署前端项目的时候,如果用户一直停留在页面上并未刷新使用,会存在功能使用差异性的问题,因此,当前端部署项目后,需要提醒用户有去重新加载页面。

技术框架

vue、js、webpack

解决方案

编译项目时动态生成一个记录版本号的文件轮询(20s、自己设定时间)这个文件,判断版本号,有新版本则通知用户刷新页面通过监听visibilitychange事件,在页面隐藏时停止轮询,页面显示立马检测一次更新检测到更新后,停止轮询

(感兴趣的可去看方案二:根据打完包之后生成的script src 的hash值去判断,每次打包都会生成唯一的hash值,只要轮询去判断不一样了,那一定是重新部署了。前端项目部署自动检测更新后通知用户刷新页面(前端实现,技术框架vue、js、webpack)——方案二:轮询去判断服务端的index.html是否跟当前的index.html的脚本hash值一样_前端更新刷新页面-CSDN博客) 

效果

页面右下角提示更新:

代码实现 

 Step1:在 vue.config.js 实现动态创建版本号文件

if (process.env.VUE_APP_ENV !== "production") {// 这里我设置的是只在非生产环境自动检测更新(生成version);// 想要所有环境都自动检测更新,只要写if(process.env.VUE_APP_ENV !== "production")内的内容就好 const { writeFile, existsSync } = require('fs') // 动态生成版本号 const createVersion = () => { //检测目录是否存在 if (existsSync('./public')) { writeFile(`./public/version.json`, `{"version":"${Date.now()}"}`, (err) => { if (err) { console.log('写入version.json失败') console.log(err) } else { console.log('写入version.json成功') } }) } else { setTimeout(createVersion, 1000) } } setTimeout(createVersion, 10000)}

 Step2:在src目录下封装 auto-update.js

/* * @Description: 自动更新 */let currentVersion // 当前版本let version // 新版本// const timeData = 60 * 1000 // 检查间隔时间const timeData = 20 * 1000 // 检查间隔时间let hidden = false // 页面是否隐藏let setTimeoutIdlet needTip = true // 默认开启提示// 获取版本号const getVersion = async () => { return fetch('/version.json?timestep=' + Date.now()).then((res) => res.json())}// 检查更新const checkUpdate = async () => { console.log('***************checkUpdate**************') const currentVersion = sessionStorage.getItem("version") version = (await getVersion()).version // 本地没有 version,表示刚进入系统,直接塞值 if (!currentVersion) return sessionStorage.setItem("version", version) console.log("🚀 ~ file: auto-update.js:19 ~ version:", version) console.log("🚀 ~ file: auto-update.js:21 ~ currentVersion:", currentVersion) console.log("🚀 ~ file: auto-update.js:23 ~ Number(version) !== Number(currentVersion):", Number(version) !== Number(currentVersion)) let needRefresh = false if (Number(version) !== Number(currentVersion)) { console.log('%c 发现新版本~~~~~~', 'color: red') needRefresh = true } return needRefresh}// 自动更新const autoUpdate = async () => { setTimeoutId = setTimeout(async () => { // 页面隐藏了就不检查更新 if (!hidden) { const willUpdate = await checkUpdate() console.log("🚀 ~ file: auto-update.js:71 ~ setTimeoutId=setTimeout ~ willUpdate, version:", willUpdate, version) if (willUpdate && needTip) { // 延时更新,防止部署未完成用户就刷新空白 setTimeout(()=>{ // ----弹框确认---先简单点弹框确认,可以用注释内的,跳过右下角通知的内容(Step3、4) // const result = confirm('发现新版本,点击确定更新') // if (result) { // sessionStorage.setItem('version', version) // location.reload() // 刷新当前页 // } // -------------- //*****右下角通知提示 */ window.dispatchEvent( new CustomEvent("onmessageUpdate", { detail: { msg: "发现系统版本更新,请刷新页面~", version: version }, }) ) //******************* */ }, 10000) needTip = false // 关闭更新提示,防止重复提醒 } } console.log("🚀 ~ file: auto-update.js:90 ~ autoUpdate ~ needTip: ", needTip) if (needTip) { console.warn('needTip autoUpdate'); autoUpdate() } }, timeData)}// 停止检测更新const stop = () => { if (setTimeoutId) { clearTimeout(setTimeoutId) setTimeoutId = '' }}// 开始检查更新const start = async () => { // currentVersion = (await getVersion()).version autoUpdate() // 监听页面是否隐藏 document.addEventListener('visibilitychange', () => { hidden = document.hidden console.log("🚀 ~ file: auto-update.js:64 ~ document.addEventListener ~ hidden, needTip:", hidden, needTip) // 页面隐藏了就不检查更新。或者已经有一个提示框了,防止重复提示。 if (!hidden && needTip) { autoUpdate() } else { stop() } })}export default { start }

Step3:编写模板 CnNotify.vue 文件

<template> <div class="cn_notify"> <div class="content"> <i class="el-icon-message-solid"></i> { { msg }} </div> <div class="footer"> <el-row class="btnBox"> <el-button type="primary" @click="onSubmit">确认刷新</el-button> <el-button @click="cancle">我知道了</el-button> </el-row> </div> </div></template><script>export default { props: { msg: { type: String, default: '', }, version: { type: String, default: '', }, }, data() { return {}; }, created() {}, methods: { // 点击确定更新 onSubmit() { sessionStorage.setItem('version', this.version) // 存入版本version location.reload() // 刷新 }, // 关闭 cancle() { this.$parent.close(); }, },};</script><style lang='scss' scoped>.cn_notify { .content { padding: 20px 0; } .footer { display: flex; justify-content: center; }}</style><style lang='scss'>.versionNotifyStyle { .el-notification__content { width: 280px !important; }}</style>

Step4:app.vue 使用组件CnNotify

<template> <div id="app"> <router-view /> </div></template><script>// 引入CnNotify组件import CnNotify from "@/components/common/CnNotify/index.vue"export default { name: 'App', components: { CnNotify, // 注册组件 }, mounted() { this.watchUpdate() }, methods: { watchUpdate() { window.addEventListener("onmessageUpdate", (res) => { console.log("🚀 ~ file: App.vue:20 ~ window.addEventListener ~ res:", res) let msg = res.detail.msg, version = res.detail.version this.$notify({ title: "版本更新提示", duration: 0, position: "bottom-right", dangerouslyUseHTMLString: true, message: this.$createElement("CnNotify", { // 使用自定义组件 ref: "CnNotify", props: { msg: msg, version: version }, }), customClass:'versionNotifyStyle', //自定义类名 }) }) }, },}</script>

 Step5:在 main.js 内使用

// 引入自动更新提醒import autoUpdate from './auto-update'// 非生产环境使用process.env.VUE_APP_ENV !== 'production' && autoUpdate.start()



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。