前端重新部署如何使用WebWorker优雅地通知用户刷新网页?

背景

当周五晚上我正准备享用美味的宵夜时,突然接到了一个紧急消息,组里的前端系统出现了bug。我皱起了眉头,放下手中的美食,立即打开了钉钉,查看了具体情况。

原来,这个bug实际上是前几天才解决过的问题。我用手指在屏幕上滑动,果然发现了解决之道------只需简单地刷新页面。原因竟是用户一直停留在页面上,而新版本发布后,他们没有及时刷新页面,导致无法获取到最新的资源。

这让我想起了一个有趣的小故事:有一次,一个小村庄里的农夫决定要建造一个全新的小桥,以便于村民们更便利地过河。他精心设计了桥梁,使用了最先进的材料。然而,当桥梁完工后,他发现村民们仍然习惯于原来的狭窄破旧的木桥,而不愿意使用新桥。原来,他们根本不知道有新桥的存在,因为从来没有人告诉过他们。

解决方案

  1. 添加manifest.json文件记录版本信息:这是一个很好的做法,可以方便地记录前端应用的版本信息。

  2. 打包时写入当前时间戳信息 :这种方式可以确保每次打包都会更新manifest.json中的版本信息,以便后续的版本比较。

  3. 引入检查更新逻辑:在入口JS中引入检查更新的逻辑是非常好的,这样可以确保应用启动时就会进行版本检查。

  • 路由守卫检查更新:使用路由守卫进行检查更新是一个不错的选择,因为它可以确保在用户每次导航到页面时都会进行检查。

  • 使用Worker轮询检查更新:这种方法也可以,但需要注意轮询的频率,过于频繁的轮询可能会给服务器带来不必要的负担。而且使用Worker可能会增加一些复杂性。

案列

  1. public文件夹下创建一个manifest.json文件,用于记录版本信息。在public文件夹下新建manifest.json文件,并写入以下内容:
javascript 复制代码
{
  "timestamp": 0,
  "msg": "这是一个示例更新提示信息"
}
  1. 修改public/index.html文件,将标签中的修改为你项目的名称,并在标签中添加以下代码,用于引入manifest.json文件:
javascript 复制代码
<link rel="manifest" href="<%= BASE_URL %>manifest.json" />
  1. 在Vue项目中的入口文件src/main.js中,引入检查更新的逻辑:
javascript 复制代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

// 引入检查更新逻辑
import '@/utils/checkUpdate'

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
  1. 创建一个工具类文件src/utils/checkUpdate.js,用于实现检查更新的逻辑:
javascript 复制代码
import router from '@/router'
import { Modal } from 'ant-design-vue'

if (process.env.NODE_ENV === 'production') {
  let lastEtag = ''
  let hasUpdate = false
  let worker = null

  async function checkUpdate() {
    try {
      let response = await fetch(`/manifest.json?v=${Date.now()}`, {
        method: 'head'
      })
      let etag = response.headers.get('etag')
      hasUpdate = lastEtag && etag !== lastEtag
      lastEtag = etag
    } catch (e) {
      return Promise.reject(e)
    }
  }

  async function confirmReload(msg = '', lastEtag) {
    worker &&
      worker.postMessage({
        type: 'pause'
      })
    try {
      Modal.confirm({
        title: '温馨提示',
        content: '系统后台有更新,请点击"立即刷新"刷新页面\n' + msg,
        okText: '立即刷新',
        cancelText: '5分钟后提示我',
        onOk() {
          worker.postMessage({
            type: 'destroy'
          })
          location.reload()
        },
        onCancel() {
          worker &&
            worker.postMessage({
              type: 'recheck',
              lastEtag: lastEtag
            })
        }
      })
    } catch (e) {}
  }

  router.beforeResolve(async (to, from, next) => {
    next()
    try {
      await checkUpdate()
      if (hasUpdate) {
        worker.postMessage({
          type: 'destroy'
        })
        location.reload()
      }
    } catch (e) {}
  })

  worker = new Worker(
    new URL('../worker/checkUpdate.worker.js', import.meta.url)
  )

  worker.postMessage({
    type: 'check'
  })
  worker.onmessage = ({ data }) => {
    if (data.type === 'hasUpdate') {
      hasUpdate = true
      confirmReload(data.msg, data.lastEtag)
    }
  }
}
  1. 创建一个Worker文件src/worker/checkUpdate.worker.js,用于实现Worker的逻辑:
javascript 复制代码
let lastEtag
let hasUpdate = false
let intervalId = ''
async function checkUpdate() {
  try {
    let response = await fetch(`/manifest.json?v=${Date.now()}`, {
      method: 'get'
    })
    let etag = response.headers.get('etag')
    let data = await response.json()
    hasUpdate = lastEtag !== undefined && etag !== lastEtag
    if (hasUpdate) {
      postMessage({
        type: 'hasUpdate',
        msg: data.msg,
        lastEtag: lastEtag,
        etag: etag
      })
    }
    lastEtag = etag
  } catch (e) {
    return Promise.reject(e)
  }
}

addEventListener('message', ({ data }) => {
  if (data.type === 'check') {
    checkUpdate()
    intervalId = setInterval(checkUpdate, 5 * 60 * 1000)
  }
  if (data.type === 'recheck') {
    hasUpdate = false
    lastEtag = data.lastEtag
    intervalId = setInterval(checkUpdate, 5 * 60 * 1000)
  }
  if (data.type === 'pause') {
    clearInterval(intervalId)
  }
  if (data.type === 'destroy') {
    clearInterval(intervalId)
    close()
  }
})

以上就是一个简单的案例,你可以在Vue项目中测试一下自动检查更新并提示用户刷新页面的功能。记得在实际项目中根据具体情况做适当的调整和优化。

相关推荐
(⊙o⊙)~哦1 小时前
JavaScript substring() 方法
前端
无心使然云中漫步1 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者1 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_2 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
麒麟而非淇淋3 小时前
AJAX 入门 day1
前端·javascript·ajax
2401_858120533 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab
阿树梢3 小时前
【Vue】VueRouter路由
前端·javascript·vue.js
随笔写4 小时前
vue使用关于speak-tss插件的详细介绍
前端·javascript·vue.js
史努比.4 小时前
redis群集三种模式:主从复制、哨兵、集群
前端·bootstrap·html
快乐牌刀片885 小时前
web - JavaScript
开发语言·前端·javascript