【问题标题】:Service worker returns offline html page for javascript filesService Worker 返回 javascript 文件的脱机 html 页面
【发布时间】:2021-12-16 17:33:38
【问题描述】:

我是服务工作者和离线功能的新手。我创建了一个简单的 service worker 来处理网络请求并在离线时返回一个离线 html 页面。这是根据 Google 的 PWA 指南创建的。

问题是服务工作者在请求javascript文件(未缓存)时返回offline.html。相反,它应该返回网络错误或其他东西。代码如下:

const cacheName = 'offline-v1900'; //increment version to update cache
// cache these files needed for offline use
const appShellFiles = [
    './offline.html',
    './css/bootstrap.min.css',
    './img/logo/logo.png',
    './js/jquery-3.5.1.min.js',
    './js/bootstrap.min.js',
];

self.addEventListener("fetch", (e) => {
  // We only want to call e.respondWith() if this is a navigation request
  // for an HTML page.
  // console.log(e.request.url);
  e.respondWith(
    (async () => {
      try {
        // First, try to use the navigation preload response if it's supported.
        const preloadResponse = await e.preloadResponse;
        if (preloadResponse) {
            // console.log('returning preload response');
          return preloadResponse;
        }

        const cachedResponse = await caches.match(e.request);
            if (cachedResponse) {
                // console.log(`[Service Worker] Fetching cached resource: ${e.request.url}`);
                return cachedResponse;
            }

        // Always try the network first.
        const networkResponse = await fetch(e.request);
        return networkResponse;
      } catch (error) {
        // catch is only triggered if an exception is thrown, which is likely
        // due to a network error.
        // If fetch() returns a valid HTTP response with a response code in
        // the 4xx or 5xx range, the catch() will NOT be called.

        // console.log("Fetch failed; returning offline page instead.", error);
        const cachedResponse = await caches.match('offline.html');
        return cachedResponse;
      }
    })()
  );

离线时,我在我的网站上打开一个 url,它会从缓存中加载页面,但并非所有资产都被缓存以供离线使用。因此,当发出网络请求时,比如说https://www.gstatic.com/firebasejs/9.1.3/firebase-app.js,我得到的响应是offline.html 页面的html。由于 javascript 错误,这会破坏页面。

它应该返回一个网络错误或其他东西。

【问题讨论】:

    标签: javascript service-worker offline-caching


    【解决方案1】:

    我认为相关的示例代码来自https://googlechrome.github.io/samples/service-worker/custom-offline-page/

    self.addEventListener('fetch', (event) => {
      // We only want to call event.respondWith() if this is a navigation request
      // for an HTML page.
      if (event.request.mode === 'navigate') {
        event.respondWith((async () => {
          try {
            // First, try to use the navigation preload response if it's supported.
            const preloadResponse = await event.preloadResponse;
            if (preloadResponse) {
              return preloadResponse;
            }
    
            const networkResponse = await fetch(event.request);
            return networkResponse;
          } catch (error) {
            // catch is only triggered if an exception is thrown, which is likely
            // due to a network error.
            // If fetch() returns a valid HTTP response with a response code in
            // the 4xx or 5xx range, the catch() will NOT be called.
            console.log('Fetch failed; returning offline page instead.', error);
    
            const cache = await caches.open(CACHE_NAME);
            const cachedResponse = await cache.match(OFFLINE_URL);
            return cachedResponse;
          }
        })());
      }
    
      // If our if() condition is false, then this fetch handler won't intercept the
      // request. If there are any other fetch handlers registered, they will get a
      // chance to call event.respondWith(). If no fetch handlers call
      // event.respondWith(), the request will be handled by the browser as if there
      // were no service worker involvement.
    });
    

    具体来说,fetch 处理程序会检查是否event.request.mode === 'navigate',如果是这种情况,则仅在脱机时返回 HTML。这就是确保您最终不会为其他类型的资源返回离线 HTML 所必需的。

    【讨论】:

    • 这会加载离线页面,但其中没有资源。请参阅appShellFiles 数组。这些文件是从离线页面加载的。
    • 我认为问题在于我的缓存没有返回缓存的文件。我可以在 Devtools > Applications > Cache storage 中看到文件已正确缓存
    • 对——关键是这个fetch 处理程序将负责离线逻辑。正如代码末尾的注释中所提到的,如果您想要额外的缓存行为(例如您的子资源),您可以在之后添加另一个 fetch 处理程序。这样,逻辑就集中在每个处理程序中,用于不同的用例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 2015-05-13
    相关资源
    最近更新 更多