管理備用回應

在某些情況下,您可能會想快取備用回應,以因應使用者離線的情況。除了快取行為之外,如果策略 (例如網路優先) 或重新驗證方案提供的策略,那麼實作備用做法是另一種選擇。

備用內容是通用、一體適用的回應,如果要求失敗,這個預留位置會比瀏覽器預設提供的預留位置更好。例如:

  • 「缺少圖片」的替代方案預留位置。
  • 替代標準「沒有可用的網路連線」的 HTML 替代方案頁面。

僅限離線網頁

如果您只需要提供自訂離線 HTML 網頁,但沒有任何其他,您可參考以下基本方案:

import {offlineFallback} from 'workbox-recipes';
import {setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

setDefaultHandler(new NetworkOnly());

offlineFallback();

上述程式碼使用了 setDefaultHandler,為所有路徑預設使用僅限網路的策略。然後執行 offlineFallback 方案,在發生錯誤時提供離線備用方案。方案會假設離線備用 HTML 檔案是名為 offline.html,並且從網路伺服器的根目錄提供。

全方位備用廣告

當網路故障或快取失敗時,workbox-strategies 提供的快取策略會持續拒絕。有助於將全域「貓」這個處理常式可處理單一處理常式函式中的所有失敗情形,以便您為不同的 request.destination 值提供不同的備用值。

以下範例使用 workbox-recipeswarmStrategyCache 方案,並設定擷取處理常式,在執行階段快取中提前提供快取項目。不過,預先快取可能更適用於您的應用程式:

import {warmStrategyCache} from 'workbox-recipes';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';

// Fallback assets to cache
const FALLBACK_HTML_URL = '/offline.html';
const FALLBACK_IMAGE_URL = '/images/image-not-found.jpg';
const FALLBACK_STRATEGY = new CacheFirst();

// Warm the runtime cache with a list of asset URLs
warmStrategyCache({
  urls: [FALLBACK_HTML_URL, FALLBACK_IMAGE_URL],
  strategy: FALLBACK_STRATEGY,
});

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // The warmStrategyCache recipe is used to add the fallback assets ahead of
  // time to the runtime cache, and are served in the event of an error below.
  // Use `event`, `request`, and `url` to figure out how to respond, or
  // use request.destination to match requests for specific resource types.
  switch (request.destination) {
    case 'document':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_HTML_URL});

    case 'image':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_IMAGE_URL});

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

在下一個步驟中,injectManifest會和 Workbox 的建構工具搭配使用預先快取備用回應,matchPrecache 方法發生錯誤時也能做為備用回應使用。

import {matchPrecache, precacheAndRoute} from 'workbox-precaching';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

// Optional: use the injectManifest mode of one of the Workbox
// build tools to precache a list of URLs, including fallbacks.
precacheAndRoute(self.__WB_MANIFEST);

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // Fallback assets are precached when the service worker is installed, and are
  // served in the event of an error below. Use `event`, `request`, and `url` to
  // figure out how to respond, or use request.destination to match requests for
  // specific resource types.
  switch (request.destination) {
    case 'document':
      // FALLBACK_HTML_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_HTML_URL);

    case 'image':
      // FALLBACK_IMAGE_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_IMAGE_URL);

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

第二種備用廣告設定的例子是,網頁經過快取之後,但網頁要求的圖片 (或其他素材資源) 未獲快取。網頁仍可在使用者離線時從快取讀取內容,但如果發生網路錯誤,可以提供備用預留位置或替代功能。

暖化執行階段快取

Workbox 會分別保留用於預先快取和執行階段快取的快取,或者在某些情況下,您可能想在不採用預先快取的情況下提前快取內容,因為您必須部署更新過的 Service Worker。

如要運用資產預先設定執行階段快取,您可以使用 workbox-recipes 中的 warmStrategyCache 方案。實際上,這項策略會在 Service Worker 的 install 事件中呼叫 Cache.addAll

import {warmStrategyCache} from 'workbox-recipes';
import {CacheFirst} from 'workbox-strategies';

// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = [
  '/offline.html',
];

warmStrategyCache({urls, strategy});

結論

管理失敗要求的備用回應需要花點工夫,但您可以事先規劃網頁應用程式,在使用者離線時提供一定程度的內容和功能。