0

我注意到当服务工作者脚本本身加载到浏览器中时,服务工作者的 fetch 事件不再被触发。例如,当我们有一个新版本的 service worker 时,旧的 service worker 的 fetch 事件不会被触发。结果,旧的 Service Worker 无法再检查新 Service Worker 的内容。

我确信这是可能的,我想知道这是否是一个错误,或者是否对此进行了任何更改。我在官方存储库或 W3C 草案中没有找到任何关于此更改的内容。

为了验证 fetch 事件没有被触发,我编写了一个带有版本号的小型示例 service worker(参见代码)。我已经通过以下方式对其进行了测试:

  1. 安装服务工作者的第一个版本
  2. 将版本号增加到两个。
  3. 重新加载页面 -> 以便在浏览器中安装新的 sw.js 文件。
  4. 检查 chrome 日志 -> ChromeLogs Chrome日志

示例“sw.js”:

const version = 1;
console.log(`SW with v${version} executed`);

async function onFetch(event) {
    // Not triggered for sw.js
    console.log(`fetching: ${event.request.url} with v${version}`);
    return await fetch(event.request);
}

async function onInstall() {
    console.log(`sw v${version} install`);
    await self.skipWaiting();
}

async function onActivate() {
    console.log(`sw v${version} activate`);
    await self.clients.claim();
}

self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
self.addEventListener('install', event => event.waitUntil(onInstall()));
self.addEventListener('activate', event => event.waitUntil(onActivate()));

从日志中我们可以看到,sw.js 文件没有被获取,但是在新的 service worker 安装之前,另一个文件(test.js)被获取了。我包含了 test.js javascript 文件,以查看服务人员是否在获取任何内容。所以从这个测试中我们可以看到,服务工作者脚本本身没有触发 fetch 事件。

我想知道的是,有没有办法在旧服务工作者中加载新的服务工作者 javascript 文件之前获取它?是否有任何其他事件使这成为可能?我不需要拦截脚本来执行或替换旧的服务工作者。我只想在加载新服务人员之前检查它的内容。

编辑

<html>
    <body>
        <h1>hello</h1>
        <script src="test.js"></script>
        <button onclick="runFetch()">fetch</button>
        <h2 id="swVersion"></h2>
        <script>
            navigator.serviceWorker.register('/sw.js'); // First Installation
            fetch('/sw.js'); // Triggers fetch event, but is independent from update routine.
            async function runFetch() {
                console.log(await fetch('/sw.js'));
            }
        </script>
    </body>
</html>
4

1 回答 1

0

由浏览器发起的Service Worker 更新检查总是绕过所有 Service Workerfetch处理程序。它可能最终由 HTTP 缓存实现,尽管所有现代浏览器默认也绕过 HTTP 缓存并直接访问网络。

我相当有信心fetch在执行服务工作人员更新检查时没有浏览器触发过以前的服务工作人员的事件处理程序,因为服务工作人员规范明确禁止这样做(更新请求的服务工作人员模式需要设置为'none')。fetch这有助于开发人员避免在处理新服务工作人员的事件时,如果旧服务工作人员做错了事情,它可能会“卡住” 。

我不知道您为什么会有其他想法——也许您正在考虑 HTTP 缓存交互。或者,您可能正在考虑一个场景,其中 Web 应用程序显式调用fetch('service-worker.js')以检查给定 URL 上是否存在服务工作人员,这触发fetch服务工作人员的处理程序来控制给定页面。但调用fetch('service-worker.js')与 service worker 更新检查有很大不同。

于 2020-04-20T19:00:16.110 回答