在某些情况下,您可能希望缓存后备响应,以防用户离线。实现回退是网络优先或过时同时重新验证等策略提供的缓存行为的替代方法。
回退是通用的通用响应,相对于请求失败时浏览器默认提供的占位符,它是一个更好的占位符。以下是一些示例:
- “缺失图像”的替代方法占位符。
- 标准“无可用网络连接”的 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-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-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 应用,使其在用户离线时提供一定程度的内容和功能。