如何从缓存加载不同的文件?

问题描述

我正在使用 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 中还有一些正式的指导。