第五階段開始,今天回頭把 Day 4 留下的空殼 Service Worker(public/sw.js)補完,讓 SyncETA Lite 真正具備離線能力。
離線功能的關鍵在於「快取策略」,常見的有幾種:
我們對靜態資源用 Cache First,對 API 資料用 Network First。
// public/sw.js
const STATIC_CACHE = 'syncetalite-static-v1';
const STATIC_ASSETS = ['/', '/index.html', '/src/style.css'];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(STATIC_CACHE).then((cache) => cache.addAll(STATIC_ASSETS))
);
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) =>
Promise.all(keys.filter((key) => key !== STATIC_CACHE).map((key) => caches.delete(key)))
)
);
});
self.addEventListener('fetch', (event) => {
const { request } = event;
// 靜態資源:Cache First
if (STATIC_ASSETS.some((asset) => request.url.endsWith(asset))) {
event.respondWith(
caches.match(request).then((cached) => cached || fetch(request))
);
return;
}
// TDX / Maps API:Network First,失敗才退回快取
if (request.url.includes('tdx.transportdata.tw') || request.url.includes('googleapis.com')) {
event.respondWith(
fetch(request)
.then((response) => {
const cloned = response.clone();
caches.open(STATIC_CACHE).then((cache) => cache.put(request, cloned));
return response;
})
.catch(() => caches.match(request))
);
}
});
在 Chrome 開發者工具的 Network 分頁,把節流選項切換成 Offline ,重新整理頁面。如果設定正確,靜態畫面應該還能顯示,最近一次成功抓到的到站資料也會作為備援顯示,而不是整頁空白或報錯。
明天我們要加上推播通知,讓使用者不用一直盯著畫面,也能收到延誤提醒。