我注意到当服务工作者脚本本身加载到浏览器中时,服务工作者的 fetch 事件不再被触发。例如,当我们有一个新版本的 service worker 时,旧的 service worker 的 fetch 事件不会被触发。结果,旧的 Service Worker 无法再检查新 Service Worker 的内容。
我确信这是可能的,我想知道这是否是一个错误,或者是否对此进行了任何更改。我在官方存储库或 W3C 草案中没有找到任何关于此更改的内容。
为了验证 fetch 事件没有被触发,我编写了一个带有版本号的小型示例 service worker(参见代码)。我已经通过以下方式对其进行了测试:
- 安装服务工作者的第一个版本
- 将版本号增加到两个。
- 重新加载页面 -> 以便在浏览器中安装新的 sw.js 文件。
- 检查 chrome 日志 -> ChromeLogs
示例“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>