workbox precacheAndRoute 不处理 window.fetch 或 XMLHttpRequest

workbox precacheAndRoute does not handle window.fetch or XMLHttpRequest

使用 workbox (5.1.3) 并设置服务时-worker.js like

precacheAndRoute([
  {url: '/version.txt', revision: 'v1' },
]);

我可以在浏览器中导航到 localhost://version.txt 并在 chrome 控制台中看到此内容是通过缓存从 workbox 中获取的。

控制台中的消息显示:

workbox Precaching is responding to: /version.txt

但是当试图通过以下方式获取我的 javascript 应用程序中的资源时:

  window
    .fetch('/version.txt')
    .then((response) => {
      if (response.status >= 200 && response.status < 300) {
        return response.text();
      } else {
        throw Error('no version');
      }
    })
    .then((data) => {
      console.log('content: ' + data);
    })
    .catch((error) => {
      console.log(error);
    });
}

fetch 命令将尝试直接从网络读取此内容并跳过工作箱预缓存。此外,在离线模拟时,我收到一个获取错误而不是缓存响应的错误。

快疯了 ;-)

您希望服务工作者拦截您的导航请求并提供您的文件。

您应该使用工作箱中的预缓存机制

例如

new routing.registerRoute(new routing.NavigationRoute(
    new precaching.createHandlerBoundToURL('/version.txt'), {
        allowlist: [new RegExp('/version.txt')]
    }
))

深入研究这个问题后 - 我发现了问题(至少在我的网站上)

完整的工作示例:

/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My New Project!</title>
</head>
<body>
  <h1>Example Service Worker</h1>
  <p>A simple Test</>
  <!-- Scripts -->
  <script src="index.js"></script>
</body>
</html>

/index.js

let registration;

var initServiceWorker = () => {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker
      .register('./sw.js')
      .then((reg) => registration = reg)
      .catch((error) => console.log('Registration failed with ' + error));
  }
}

var fetchTest = () => {
  console.log('VERSION FETCH Test looking for: /version.txt');
  window
    .fetch('/version.txt', { method: 'GET'})
    .then((response) => {
      if (response.status >= 200 && response.status < 300) {
        return response.text();
      } else {
        throw Error('no version.txt file');
      }
    })
    .then((data) => {
      console.log('AVILABLE VERSION FETCH: ' + String(data).trim());
    })
    .catch((error) => {
      console.log(error);
    });
}

var xmlhttpTest = () => {
  console.log('VERSION XHR Test looking for: /version.txt');

  var xhr = new XMLHttpRequest();
  xhr.open("GET", '/version.txt', true);

  xhr.onload = function (e) {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        console.log('AVILABLE VERSION XHR: ' + xhr.responseText);
      }
    }
  }

  // initialize request
  xhr.send(null);
}

console.log("JavaScript is amazing!");

initServiceWorker();

setTimeout(() => fetchTest(), 5000);

setTimeout(() => xmlhttpTest(), 10000);

setTimeout(() => { console.log('Registration update ...'); registration.update()}, 20000);

setTimeout(() => fetchTest(), 30000);

setTimeout(() => xmlhttpTest(), 35000);

/sw.js

// Sample service worker
const SW_VERSION = 'a2';

self.addEventListener('install', (event) => {
  console.log('SW INSTALL: ' + SW_VERSION);
  skipWaiting();
});

self.addEventListener('activate', (event) => {
  console.log('SW ACTIVATE: ' + SW_VERSION);
  skipWaiting();
});

self.addEventListener("fetch", function(event) {
  console.log('WORKER (' + SW_VERSION + '): fetch event in progress ... ' + event.request.url);
  if (event.request.method !== 'GET') {
    console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
    return;
  }
});

/version.txt

v1.0.0

您可能会查看您的控制台,看看在使用 FETCH 或 XMLHTTREQUEST 时,来自服务工作者的获取事件也会丢弃一条消息。


现在关于(我的)问题:

如果将带有 fetch 和 xmlHttprequest 的 javascript (/index.js) 与 service-worker (/sw.js) everything 放在同一位置(范围)按预期工作

但是

如果将 javascript 留在子文件夹中,例如 (/js/index.js) 这不会触及来自服务工作者的获取监听器 (/ sw.js) 更多 即使 /js 应该在范围内???

很奇怪但很高兴现在得到它 ;-)