问题描述
我正在使用 Service Worker 提供一个显示用户离线的回退页面。 Service Worker 在拦截请求期间获取相同的请求,并在获取错误时从缓存中提供对“offline.html”请求的响应。这样做的一小部分是。
self.addEventListener("fetch",(event) => {
event.respondWith(
caches.match(event.request).then(() => {
return fetch(event.request).catch((err) => {
return caches.match("offline.html");
});
})
);
});
现在如果离线 html 有其他请求,可能是它的 css 文件或图像,我如何从缓存中加载它们。我尝试执行以下操作:
self.addEventListener("fetch",(event) => {
event.respondWith(
caches.match(event.request).then(() => {
return fetch(event.request).catch((err) => {
let url = event.request.url;
if(url.endsWith('.css')) return caches.match('offline.css');
if(url.endsWith('.jpg') || url.endsWith('.png')) return caches.match('images/banner.jpg');
return caches.match("offline.html");
});
})
);
});
但是有没有更好的方法来做到这一点?有没有标准的方法来做到这一点?
解决方法
首先,我建议您在决定是否使用 onscroll
作为后备内容之前先检查一下是否 event.request.destination === 'document'
。这可确保您不会意外返回 HTML 文档以满足(例如,碰巧失败的随机 API 请求)。
此外,您当前的代码包含 offline.html
但实际上并未使用缓存的响应,这可能不是您想要的。
也就是说,让我们来看看我认为您想要的逻辑:
- 您的 Service Worker 尝试向网络发出请求。
- 如果该请求返回有效响应,请使用它,您就大功告成了。
- 如果该请求失败,则:
- 如果是导航请求,无论目标网址如何,都使用缓存的
caches.match(event.request)
作为响应。 - 否则,对于非导航请求(如 CSS 或 JS 请求),请使用与响应所需 URL 匹配的缓存条目。
- 如果是导航请求,无论目标网址如何,都使用缓存的
这是一个实现该功能的 Service Worker。您需要确保 CSS、JS 和 offline.html
资产为 cached during service worker installation;这仅包括 offline.html
处理程序逻辑。
fetch
在 this article 中还有一些正式的指导。