关于vue.js:vue项目部署后提示用户有新版本

107次阅读

共计 3178 个字符,预计需要花费 8 分钟才能阅读完成。

你可能在浏览器见到过下面这种 UI,这是在 vue 我的项目从新 build 在服务端部署后,浏览器刷新页面弹出的提醒,这时如果用户点击更新就会重载页面,革除之前的缓存获取最新内容。

这是怎么产生的呢?你可能会想到上面的形式:

  • 服务端编译重新部署保护一个版本号,客户端通过轮询检测和本地存储的是否雷同,发现更新的版本就弹框提醒(毛病 耗电。尤其是在挪动端)
  • 通过在 html 中做版本标记 …
  • websocket 长连贯像客户端推送版本更新(繁琐)
  • service worker

通过观察截图左下角的红框,能够看出这个网站采纳形式是 注册了 service worker

当刷新页面后之前注册的 service worker 的 updated(){} 生命周期中监听到有新的内容可供更新,触发更新弹框,提醒用户更新。

这种形式只需前端解决,不须要服务端做任何工作。只有每次 build 后从新在服务端部署,有文件产生变动,就能够被 service worker 发现。

这篇文章就来记录一下怎么做。

引入 cli-plugin-pwa

参考 vue 我的项目引入 pwa 使网页利用可装置

在下面的根底上,向下进行。

在 registerServiceWorker.js 增加事件触发

/* eslint-disable no-console */

import {register} from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {register(`${process.env.BASE_URL}service-worker.js`, {ready () {
      console.log(
        'App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB'
      )
    },
    registered () {console.log('Service worker has been registered.')
    },
    cached () {console.log('Content has been cached for offline use.')
    },
    updatefound () {console.log('New content is downloading.')
    },
    updated (registration) {console.log('New content is available; please refresh.')
      document.dispatchEvent(new CustomEvent('swUpdated', { detail: registration})
      )
    },
    offline () {console.log('No internet connection found. App is running in offline mode.')
    },
    error (error) {console.error('Error during service worker registration:', error)
    }
  })
}

在 updated() {} 中增加 swUpdated 自定义事件,而后在 ReloadPrompt.vue 组件中监听事件,有更新时弹出 提醒用户更新。

这个组件须要在 App.vue 中引入,或者其余适合的中央。

<!-- ReloadPrompt.vue -->
<template>
  <div>
    <!-- <el-button @click="handlePrompt(true)">show</el-button> -->
    <transition name="el-zoom-in-bottom">
      <el-card class="fix_right_bottom" v-if="visible">
        <div style="padding: 14px;">
          <span style="font-size: 14px;">
            发现新版本,点击 "更新" 获取。</span>
          <div class="button_group">
            <el-button size="mini" @click="handlePrompt(false)"> 敞开 </el-button>
            <el-button type="primary" size="mini" @click="refreshApp"> 更新 </el-button>
          </div>
        </div>
      </el-card>
    </transition>
  </div>
</template>

<script>
export default {created() {document.addEventListener('swUpdated', this.updateAvailable, { once: true})

    navigator.serviceWorker.addEventListener('controllerchange', () => {
      // We'll also need to add'refreshing' to our data originally set to false.
      if (this.refreshing) return
      this.refreshing = true
      // Here the actual reload of the page occurs
      window.location.reload()})
  },
  data() {
    return {
      visible: false,
      registration: null,
      refreshing: false
    }
  },
  methods: {handlePrompt(val) {this.visible = val},
    updateAvailable(event) {
      this.registration = event.detail
      this.visible = true
    },
    refreshApp() {
      this.visible = false
      // Make sure we only send a 'skip waiting' message if the SW is waiting
      if (!this.registration || !this.registration.waiting) return
      // Send message to SW to skip the waiting and activate the new SW
      this.registration.waiting.postMessage({type: 'SKIP_WAITING'})
    }
  }
}
</script>

<style scoped>
.fix_right_bottom {
  position: fixed;
  right: 20px;
  bottom: 20px;
}
.button_group {margin-top: 10px;}
</style>
// service-worker.js

// install new service worker when ok, then reload page.
self.addEventListener("message", msg => {if (msg.data && msg.data.type === 'SKIP_WAITING'){self.skipWaiting()
    }
})

从新来看一下这个流程,上一版的网页注册了 service-worker.js,服务端从新 build 部署,有新内容呈现,=> 客户端刷新 => 发现有新的 service-worker 能够装置 => 触发 updated(){} => ReloadPrompt.vue => 触发一次 “swUpdated” => 弹出更新弹框用户点击更新 => 向 service-worker.js 传递 “SKIP_WAITING” => 新的 service-worker.js 装置后 => 触发 ReloadPrompt.vue 中的 “controllerchange” 实现页面重载。

这样就解决了 spa 利用让人头疼的缓存问题。

正文完
 0