前端重新部署如何使用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项目中测试一下自动检查更新并提示用户刷新页面的功能。记得在实际项目中根据具体情况做适当的调整和优化。

相关推荐
腾讯TNTWeb前端团队3 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰6 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪7 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪7 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy7 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom8 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom8 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom8 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom8 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom8 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试