javascript - 如何在所有其他请求之前加载服务人员?
问题描述
我试图在页面上的所有子资源请求之前加载服务工作者,以便我可以对加载子资源的方式应用一些优化(例如延迟加载,加载资产的缩小版本而不是完整资产)。但是,我找不到在其他子资源请求开始之前加载我的软件的方法。
我创建了一个简单的概念验证,说明我正在尝试对我的 Service Worker 处理的任何请求执行 401(只是为了更容易找到我的 SW 何时开始处理请求)。
这是我的 HTML:
<!doctype html>
<head>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/dl-wps-sw.js', { scope: '/' }).then(function (registration) {
console.log('Service Worker registration successful with scope: ', registration.scope);
}, function (err) {
console.error(err);
});
}
</script>
...
这是我的服务人员:
self.addEventListener('install', function (event) {
self.skipWaiting();
});
self.addEventListener('activate', () => {
self.clients.claim();
});
self.addEventListener('fetch', (event) => {
const init = {status: 401, statusText: 'Blocked!'};
event.respondWith(new Response(null, init));
});
正如您在屏幕截图中看到的那样,尽管我注册 Service Worker 的代码位于页面的最顶部,但它直到稍后才激活并开始处理请求,到那时我会收到大量关键请求需要赶上已经开除了。
在 Service Worker 规范的 Github 问题中,我发现其他人似乎正在尝试做我想要完成的事情(2 年前):https ://github.com/w3c/ServiceWorker/issues/1282
他们似乎建议使用<link rel="serviceworker"...
标签来执行此操作,但由于某种原因,此链接类型似乎已从 Chrome 中删除:https ://www.chromestatus.com/feature/5682681044008960
我尝试了其他几个想法来尝试首先加载我的软件:
- 用
<link rel="preload"...
标签预加载我的软件 fetch
用/预加载我的 SWXMLHttpRequest
- 在 HTML 中内联 Service Worker(显然不可能)
- 通过运行几秒钟的while循环来延迟页面的执行(这有点工作,但它是一个可怕的不可预测的黑客攻击)
我缺少任何想法或策略吗?我的 Google-fu 未能让我想出一个解决方案。
解决方案
您需要先单独安装软件,然后刷新页面。然后,SW 可以为启用 SW 的页面提供内容并拦截所有其他请求。示例:fetch-progress.anthum.com
索引.html
<p>Installing Service Worker, please wait...</p>
<script>
navigator.serviceWorker.register('sw.js')
.then(reg => {
if (reg.installing) {
const sw = reg.installing || reg.waiting;
sw.onstatechange = function() {
if (sw.state === 'installed') {
// SW installed. Refresh page so SW can respond with SW-enabled page.
window.location.reload();
}
};
} else if (reg.active) {
// something's not right or SW is bypassed. previously-installed SW should have redirected this request to different page
handleError(new Error('Service Worker is installed and not redirecting.'))
}
})
.catch(handleError)
function handleError(error) {}
</script>
sw.js
self.addEventListener('fetch', event => {
const url = event.request.url;
const scope = self.registration.scope;
// serve index.html with service-worker-enabled page
if (url === scope || url === scope+'index.html') {
const newUrl = scope+'index-sw-enabled.html';
event.respondWith(fetch(newUrl))
} else {
// process other files here
}
});
index-sw-enabled.html
<!--
This page shows after SW installs.
Put your main app content on this page.
-->
推荐阅读
- sql - 如何从 SQL XML 列中提取值列表
- python - 在 python-3.x 之后如何打印并使程序不执行任何操作
- reactjs - 无法覆盖 react-date-picker 中的样式
- java - 无法弄清楚我的 getter 方法哪里出错了(Java)
- asp.net - 动态循环模型项
- javascript - 寻找一种方法来合并数组内的 Javascript 对象键,仅在匹配的 Id 上。地图?平面图?
- powerbi-desktop - Power BI Desktop 按人员姓名添加两行的值
- flutter - 在 VSCode 中为 dartfmt 添加参数
- ubuntu - Ubuntu 20.04 Spamassassin 安装在“chmod:无法访问'/var/lib/spamassassin/compiled'”时失败
- python - Django rest框架我需要在响应之前关闭文件吗