基於service-worker實現部署後提示使用者重新整理
阿新 • • 發佈:2022-05-06
Vue專案部署新版本後提示使用者重新整理瀏覽器
vue-cli 建立帶pwd的專案
vue create pwa-product
# 選擇 pwd
修改 src/registerServiceWorker.js
/* 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(); } });