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

背景

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

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

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

解决方案

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

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

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

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

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

案列

  1. public文件夹下创建一个manifest.json文件,用于记录版本信息。在public文件夹下新建manifest.json文件,并写入以下内容:
{
  "timestamp": 0,
  "msg": "这是一个示例更新提示信息"
}

  1. 修改public/index.html文件,将标签中的修改为你项目的名称,并在标签中添加以下代码,用于引入manifest.json文件:
<link rel="manifest" href="<%= BASE_URL %>manifest.json" />
  1. 在Vue项目中的入口文件src/main.js中,引入检查更新的逻辑:
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,用于实现检查更新的逻辑:
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的逻辑:
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项目中测试一下自动检查更新并提示用户刷新页面的功能。记得在实际项目中根据具体情况做适当的调整和优化。

相关推荐

  1. 如何在Flask中优雅使用装饰器刷新令牌

    2024-03-15 04:44:01       9 阅读
  2. Spring Boot 优雅处理重复请求

    2024-03-15 04:44:01       38 阅读
  3. vite vue3中使用 webworker

    2024-03-15 04:44:01       19 阅读
  4. 详解 WebWorker 的概念、使用场景、示例

    2024-03-15 04:44:01       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-15 04:44:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-15 04:44:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-15 04:44:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-15 04:44:01       18 阅读

热门阅读

  1. 什么是API签名认证?

    2024-03-15 04:44:01       21 阅读
  2. 2024年科技前瞻:AI辅助研发引领未来创新浪潮

    2024-03-15 04:44:01       20 阅读
  3. Android JNI常用API函数介绍

    2024-03-15 04:44:01       19 阅读
  4. 有来团队后台项目-解析10

    2024-03-15 04:44:01       23 阅读
  5. Qt/QML编程之路:线程及Slot的指针传递(47)

    2024-03-15 04:44:01       18 阅读
  6. 2024.3.14 训练记录(16)

    2024-03-15 04:44:01       19 阅读
  7. 大模型prompt提示词如何调优?

    2024-03-15 04:44:01       18 阅读
  8. 【点云】激光点云建图评测

    2024-03-15 04:44:01       18 阅读
  9. OpenAI GPT-4.5 Turbo 泄露,六月或将发布

    2024-03-15 04:44:01       20 阅读
  10. 4. git 添加版本标签

    2024-03-15 04:44:01       21 阅读
  11. Oracle控制文件control file(1)控制文件概述

    2024-03-15 04:44:01       21 阅读
  12. 电子信息工程实践案例分析报告

    2024-03-15 04:44:01       20 阅读
  13. PHP伪协议详解

    2024-03-15 04:44:01       22 阅读
  14. LeetCode(力扣)算法题_2864_最大二进制奇数

    2024-03-15 04:44:01       19 阅读