管理備用回應

在某些情況下,您可能需要快取備用回應,以防使用者離線。除了網路優先或過時的重新驗證等策略提供的快取行為外,導入備用機制可替代快取行為。

備用廣告是一種通用的通用回應,是與瀏覽器在要求失敗時預設提供的預留位置。這個預留位置是較合適的預留位置。例如:

  • 「缺少圖片」預留位置的替代方案。
  • 標準「沒有可用的網路連線」網頁的 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 提供的快取策略將持續拒絕。如此一來,您就能透過設定全域「catch」處理常式處理單一處理常式函式中任何失敗的模式,以便為不同的 request.destination 值提供不同的備用項。

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

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-recipeswarmStrategyCache 方案。基本上,這項策略會在 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});

結語

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