1. 程式人生 > 其它 >基於service-worker實現部署後提示使用者重新整理

基於service-worker實現部署後提示使用者重新整理

Vue專案部署新版本後提示使用者重新整理瀏覽器

vue-cli 建立帶pwd的專案

vue create pwa-product

# 選擇 pwd

修改 src/registerServiceWorker.js

registerServiceWorker

/* eslint-disable no-console */

import { register } from "register-service-worker";

if (process.env.NODE_ENV === "production" && navigator.serviceWorker) {
  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(registration) {
      console.log("Service worker has been registered.");
      // 通過測試新的服務工作執行緒來定期檢查應用更新
      setInterval(() => {
        registration.update();
      }, 1000); // 這裡為了測試 每秒檢查一次
    },
    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.");
        //  建立一個自定義事件
      const event = new CustomEvent("swupdatefound", { detail: registration });
        // 觸發這個事件
      document.dispatchEvent(event);
    },
    offline() {
      console.log(
        "No internet connection found. App is running in offline mode."
      );
    },
    error(error) {
      console.error("Error during service worker registration:", error);
    },
  });

  let refreshing;
    // 監聽需要更新事件  呼叫 window.location.reload()
  navigator.serviceWorker.addEventListener("controllerchange", function () {
    if (refreshing) return;

    window.location.reload();

    refreshing = true;
  });
}

在頁面中新增事件監聽

在 main.js 或 store 中新增事件監聽

// 新增對應自定義事件的監聽
document.addEventListener("swupdatefound", (e) => {
  // 提示使用者重新整理
  let res = confirm("新內容可用,請重新整理");
  if (res) {
    // e.detail == registration
    // waiting.postMessage({ type: "SKIP_WAITING" }) 是固定寫法 
    // 用於觸發更新  navigator.serviceWorker.addEventListener("controllerchange"...)
    e.detail.waiting.postMessage({
      type: "SKIP_WAITING",
    });
  }
});

為什麼 waiting.postMessage({ type: "SKIP_WAITING" }) 會觸發更新

在打包下的 dist 目錄下service-worker.js 看到一下程式碼

// self 是 worker 子執行緒的標準
//  waiting.postMessage({ type: "SKIP_WAITING" }) 會觸發下面事件監聽
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    //   呼叫 觸發 controllerchange
    self.skipWaiting();
  }
});