管理回退响应

在某些情况下,您可能需要缓存后备响应,以防用户离线。实现回退是缓存行为的替代方案,诸如网络优先或过时重新验证等策略可提供这种行为。

后备是通用的通用响应,与请求失败时浏览器默认提供的响应相比,它是一种更好的占位符。以下是一些示例:

  • “缺失的图片”占位符的替代值。
  • 标准“无可用网络连接”网页的 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 配方,并设置了 catch 处理程序以在运行时缓存中提前缓存的内容。但是,预缓存回退可能更适合您的应用:

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});

总结

管理失败请求的回退响应需要花费一些精力,但只要提前规划,您便可以将 Web 应用设置为在用户离线时提供一定程度的内容和功能。