本程式碼研究室將說明如何使用 Workbox 實作具彈性的搜尋功能。這個應用程式使用的試用版應用程式內含搜尋框,會呼叫伺服器端點,並將使用者重新導向至基本 HTML 網頁。
測量
新增最佳化之前,最好先分析應用程式的目前狀態。
- 按一下「Remix to Edit」即可編輯專案。
- 如要預覽網站,請按下「查看應用程式」。然後按下 全螢幕 。
在新開啟的分頁中查看網站離線時的行為:
- 按下 Control+Shift+J 鍵 (或在 Mac 上為 Command+Option+J 鍵) 開啟開發人員工具。
- 按一下 [網路] 分頁標籤。
- 開啟 Chrome 開發人員工具,然後選取「網路」面板。
- 在分類下拉式清單中,選取「離線」。
- 在試用版應用程式中輸入搜尋查詢,然後按一下「搜尋」按鈕。
以下顯示標準瀏覽器錯誤網頁:
提供備用回應
Service Worker 含有用來將離線網頁新增至預快取清單的程式碼,因此可以隨時在 Service Worker install
事件進行快取。
一般來說,您會需要指示 Workbox 在建構期間將此檔案新增至預先快取清單,方法是將程式庫與您選擇的建構工具 (例如 webpack 或 gulp) 進行整合。
為了方便起見,我們已經為您完成相關作業。位於 public/sw.js
的下列程式碼會執行此操作:
const FALLBACK_HTML_URL = '/index_offline.html';
…
workbox.precaching.precacheAndRoute([FALLBACK_HTML_URL]);
接著,請新增程式碼,使用離線網頁做為備用回應:
- 如要查看來源,請按下「檢視來源」。
- 將以下程式碼新增至
public/sw.js
的底部:
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());
workbox.routing.setCatchHandler(({event}) => {
switch (event.request.destination) {
case 'document':
return caches.match(FALLBACK_HTML_URL);
break;
default:
return Response.error();
}
});
該程式碼會執行以下作業:
- 定義適用於所有請求的預設僅限聯播網策略。
- 呼叫
workbox.routing.setCatchHandler()
以管理失敗的要求,藉此宣告全域錯誤處理常式。當要求提出文件要求時,系統會傳回備用離線 HTML 網頁。
如何測試這項功能:
- 返回執行應用程式的另一個分頁。
- 將「Throttling」下拉式清單設為「Online」。
- 按下 Chrome 的「返回」按鈕即可返回搜尋頁面。
- 確認開發人員工具中的「停用快取」核取方塊已停用。
- 長按 Chrome 的「重新載入」按鈕,然後選取 清除快取並強制重新載入 確認您的 Service Worker 已更新。
- 再次將「Throttling」下拉式清單重新設為「離線」。
- 輸入搜尋查詢,然後再次點選「搜尋」按鈕。
系統會顯示下列備用 HTML 網頁:
要求通知權限
為簡單起見,views/index_offline.html
的離線網頁已經在指令碼區塊底部的程式碼區塊中,加入要求通知權限的程式碼:
function requestNotificationPermission(event) {
event.preventDefault();
Notification.requestPermission().then(function (result) {
showOfflineText(result);
});
}
該程式碼會執行以下作業:
- 當使用者按一下「訂閱通知」時,系統會呼叫
requestNotificationPermission()
函式,該函式會呼叫Notification.requestPermission()
來顯示預設的瀏覽器權限提示。承諾使用使用者選取的權限 (可能是granted
、denied
或default
) 解決。 - 將已解決的權限傳送至
showOfflineText()
,以便向使用者顯示適當的文字。
保留離線查詢,並在恢復連線時重試
接下來,請實作 Workbox 背景同步處理來保存離線查詢,以便在瀏覽器偵測到連線傳回時重試。
- 開啟
public/sw.js
進行編輯。 - 在檔案結尾加入下列程式碼:
const bgSyncPlugin = new workbox.backgroundSync.Plugin('offlineQueryQueue', {
maxRetentionTime: 60,
onSync: async ({queue}) => {
let entry;
while ((entry = await queue.shiftRequest())) {
try {
const response = await fetch(entry.request);
const cache = await caches.open('offline-search-responses');
const offlineUrl = `${entry.request.url}¬ification=true`;
cache.put(offlineUrl, response);
showNotification(offlineUrl);
} catch (error) {
await this.unshiftRequest(entry);
throw error;
}
}
},
});
該程式碼會執行以下作業:
workbox.backgroundSync.Plugin
包含將失敗的要求新增至佇列的邏輯,方便稍後重試。這些要求會保存在 IndexedDB 中。maxRetentionTime
表示可重試要求的時間長度。舉例來說,我們選擇了 60 分鐘 (之後就會遭到捨棄)。onSync
是此程式碼最重要的部分。系統會在連線恢復時呼叫此回呼,藉此擷取佇列中的要求,然後從網路中擷取。- 網路回應會新增至
offline-search-responses
快取,並附加¬ification=true
查詢參數,讓當使用者點選通知時,就能擷取這個快取項目。
如要將背景同步處理功能整合至您的服務,請針對傳送至搜尋網址 (/search_action
) 的要求定義 NetworkOnly 策略,並傳遞先前定義的 bgSyncPlugin
。將以下程式碼新增至 public/sw.js
的底部:
const matchSearchUrl = ({url}) => {
const notificationParam = url.searchParams.get('notification');
return url.pathname === '/search_action' && !(notificationParam === 'true');
};
workbox.routing.registerRoute(
matchSearchUrl,
new workbox.strategies.NetworkOnly({
plugins: [bgSyncPlugin],
}),
);
這麼做可指示 Workbox 一律前往網路,並在要求失敗時使用背景同步處理邏輯。
接著,將下列程式碼新增至 public/sw.js
底部,針對來自通知的要求定義快取策略。使用 CacheFirst 策略,以便從快取提供。
const matchNotificationUrl = ({url}) => {
const notificationParam = url.searchParams.get('notification');
return (url.pathname === '/search_action' && (notificationParam === 'true'));
};
workbox.routing.registerRoute(matchNotificationUrl,
new workbox.strategies.CacheFirst({
cacheName: 'offline-search-responses',
})
);
最後,新增用於顯示通知的程式碼:
function showNotification(notificationUrl) {
if (Notification.permission) {
self.registration.showNotification('Your search is ready!', {
body: 'Click to see you search result',
icon: '/img/workbox.jpg',
data: {
url: notificationUrl
}
});
}
}
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});
測試功能
- 返回執行應用程式的另一個分頁。
- 將「Throttling」下拉式清單設為「Online」。
- 按下 Chrome 的「返回」按鈕即可返回搜尋頁面。
- 長按 Chrome 的「重新載入」按鈕,然後選取 清除快取並強制重新載入 確認您的 Service Worker 已更新。
- 再次將「Throttling」下拉式清單重新設為「離線」。
- 輸入搜尋查詢,然後再次點選「搜尋」按鈕。
- 按一下「訂閱通知」。
- 當 Chrome 詢問是否要授予應用程式傳送通知的權限時, 請按一下「Allow」(允許)。
- 輸入其他搜尋查詢,然後再次點選「搜尋」按鈕。
- 再次將「Throttling」下拉式清單重新設定為「Online」。
連線恢復後,系統會顯示以下通知:
結論
Workbox 提供許多內建功能,可讓您的 PWA 更彈性且更具吸引力。 在本程式碼研究室中,您已瞭解如何透過 Workbox 抽象化實作 Background Sync API,確保離線使用者查詢不會遺失,且可在連線恢復後重試。 這個示範版是一款簡單的搜尋應用程式,但您也可以運用類似的實作方式,處理更複雜的情境和用途,包括發布即時通訊應用程式,以及在社群網路上張貼訊息等。