動態

詳情 返回 返回

vue項目部署後提示用户有新版本 - 動態 詳情

在這裏插入圖片描述

你可能在瀏覽器見到過上面這種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應用讓人頭疼的緩存問題。
user avatar zaotalk 頭像 aqiongbei 頭像 chongdianqishi 頭像 leexiaohui1997 頭像 Dream-new 頭像 imba97 頭像 youyoufei 頭像 huangmingji 頭像 geeklab 頭像 weishiledanhe 頭像 leoych 頭像 taotao123 頭像
點贊 53 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.