PWA 背景同步技術實作 運用 Periodic Sync API 確保在網路不穩時資料更新

me
林彥成
2021-09-23 | 3 min.
文章目錄
  1. 1. 什麼是 PWA 背景同步 (Periodic Background Sync)?
  2. 2. 什麼是 Periodic Background Sync API?
  3. 3. Periodic Background Sync API 實作指南
    1. 3.1. 1. 查看權限
    2. 3.2. 2. 註冊事件,並給予一個 tag 辨識
    3. 3.3. 3. 查看是否註冊成功
    4. 3.4. 4. 監聽並處理剛才註冊的事件
    5. 3.5. 5. 取消註冊的事件
  4. 4. FAQ:PWA 背景同步常見問題
    1. 4.1. Q1:為什麼我實作了 API 但背景同步卻沒有按時觸發?
    2. 4.2. Q2:iOS 支援 Periodic Background Sync 嗎?
    3. 4.3. Q3:minInterval 設定多久比較合適?

什麼是 PWA 背景同步 (Periodic Background Sync)?

PWA 背景同步 (Periodic Background Sync) 是一種 Web API,允許 Progressive Web App (PWA) 在使用者未開啟網頁的情況下,仍能透過 Service Worker 在背景定期從伺服器抓取最新資料。其核心目標在於優化弱網或無網路環境下的使用者體驗,例如:在網路恢復時自動下載最新的新聞文章或更新快取。這項技術解決了傳統網頁必須在「前景開啟」才能更新資料的侷限,讓 Web App 具備如同原生 App 般「開機即最新」的自動同步能力。


什麼是 Periodic Background Sync API?

透過在 Service Worker 中搭配 Periodic Background Sync API,我們可以讓 Web App 具備「定期背景同步資料」的神奇效果。

您是否遇過這種情況:在連假坐火車返鄉時,網路訊號總是斷斷續續,網頁頻頻因為連線不良而「轉圈圈」?小編覺得這種體驗非常打擊用戶信心。雖然 Service Worker 的快取機制解決了部分問題,但當頁面需要「最新資料」時,如果沒有適當的處置,用戶只會收到連線逾時的錯誤。

這就是 PWA 背景同步教學 的價值所在:它能優化極端環境下的操作體驗。


優化過後的使用者歷程會可能像下面這樣:

  1. 閱讀任何文章
  2. 斷線
  3. 點擊另一篇文章
  4. 知頁面載入失敗
  5. 同意通知
  6. 關閉瀏覽器 (App)
  7. 恢復網路
  8. 當文章下載、快取後並準備好時就會收到通知

以上的情境 Google 有提供舊版 API 的教學並提供的 Demo 影片如下:

Periodic Background Sync API 實作指南

早期的開發是透過 SyncManager.register() 來完成,但小編要在這邊提醒大家,目前的標準化寫法更推薦使用 ServiceWorkerRegistration.periodicSync.register()

相關技術標準可以參考:WICG 規範文件

在進行 Background Sync API 實作 時,流程其實並不複雜。只要瀏覽器支援,我們就能透過以下步驟完成 PWA 背景同步 的設定。為了程式的強健性,記得加上 try-catch 進行防呆。

1
2
3
4
5
6
7
8
// 先抓出來 registration
const registration = await navigator.serviceWorker.ready;

// 判斷有沒有這個 API
if ("periodicSync" in registration) {
// 拿出來會是一個物件
const periodicSync = registration.periodicSync;
}

使用流程如下:

1. 查看權限

在使用 API 前,必須確認使用者已授予相關權限。

2. 註冊事件,並給予一個 tag 辨識

底下的例子為 get-latest-news

1
2
3
4
5
6
7
8
9
10
11
async function registerPeriodicNewsCheck() {
const registration = await navigator.serviceWorker.ready;
try {
// 註冊定期同步事件,minInterval 單位為毫秒
await registration.periodicSync.register("get-latest-news", {
minInterval: 24 * 60 * 60 * 1000, // 建議最小間隔為 24 小時
});
} catch {
console.log("此瀏覽器不支援 Periodic Background Sync");
}
}

3. 查看是否註冊成功

1
2
3
4
5
6
7
8
navigator.serviceWorker.ready.then((registration) => {
registration.periodicSync.getTags().then((tags) => {
if (tags.includes("get-latest-news")) {
// 若已註冊成功,則可跳過網頁載入時的下載流程
skipDownloadingLatestNewsOnPageLoad();
}
});
});

4. 監聽並處理剛才註冊的事件

在 Service Worker (sw.js) 中監聽:

1
2
3
4
5
6
7
8
9
10
11
async function updateArticles() {
const articlesCache = await caches.open("articles");
await articlesCache.add("/api/articles");
}

self.addEventListener("periodicsync", (event) => {
if (event.tag == "get-latest-news") {
// 確保非同步操作完成前 Worker 不會被終止
event.waitUntil(updateArticles());
}
});

5. 取消註冊的事件

1
2
3
navigator.serviceWorker.ready.then((registration) => {
registration.periodicSync.unregister("get-latest-news");
});

FAQ:PWA 背景同步常見問題

Q1:為什麼我實作了 API 但背景同步卻沒有按時觸發?

A:瀏覽器(如 Chrome)通常會對背景同步施加「使用者參與度(User Engagement)」限制。如果您不常使用該 PWA,瀏覽器會降低甚至停止同步頻率以節省電量。此外,裝置若處於「省電模式」或「網路流量受限」環境,同步也可能被暫停。

Q2:iOS 支援 Periodic Background Sync 嗎?

A:截至目前為止,iOS Safari 尚未支援 periodicSync。這項功能目前主要在 Android 版 Chrome 與桌面版 Chromium 瀏覽器(如 Edge)中運作。在 iOS 上,建議使用傳統的 Service Worker 快取策略作為替代。

Q3:minInterval 設定多久比較合適?

A:建議設定為 24 小時 (24 * 60 * 60 * 1000) 或更長。過短的間隔(如幾分鐘一次)通常會被瀏覽器拒絕,因為這會消耗過多電池與流量。請記住,這是一個「建議」間隔,實際執行時間由瀏覽器調度。


喜歡這篇文章,請幫忙拍拍手喔 🤣