javascript - 用 fetch 事件替换 service worker 中的资产
问题描述
我正在尝试与我的服务人员热切换主题样式表。
我为 Jekyll 创建了一个主题(与 GitHub Pages 一起使用),并希望能够在深色主题和浅色主题之间进行替换(“关灯”)并使其保持一致。
现在,这是通过将状态保存到localstorage
并据此替换主题link
元素来实现的。
问题是,在获取原始白色主题之后进行检查,因此即使localstorage
设置了深色主题,用户也会看到白色主题的闪光
这是它目前的行为方式(按钮位于右上角): https ://thatkookooguy.github.io/postmortem-demo/postmortem/002
更改主题后,尝试导航到另一个页面。页面以白色主题加载,然后更改为深色主题
我想我可以通过在服务工作者中切换脚本来解决这个问题,因为我可以addEventListener
到fetch
事件并用另一个提取替换它在承诺链中。
但是代码似乎不起作用。如果我在事件回调中添加一个调试点,它永远不会触发(不是在资产上,也不是在实际页面获取上)
HTML头
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet prefetch' href='//fonts.googleapis.com/css?family=Fredoka+One|Righteous'>
<!-- THIS SHOULD BE INTERCEPTED BY THE SERVICE WORKER -->
<link id="bulma-theme" rel="stylesheet prefetch" href="//unpkg.com/bulmaswatch/default/bulmaswatch.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="{{ site.baseurl }}/assets/style.css" />
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('{{ site.baseurl }}/assets/sw.js')
.then(function() {
console.log("Service Worker Registered");
});
}
</script>
</head>
服务工作者代码
importScripts('localforage.min.js');
// remember the theme
this.onmessage = function(msg) {
if (!msg.data.theme) {
return;
}
localforage.setItem('theme', msg.data.theme);
}
// replace link fetching with correct theme
this.addEventListener('fetch', function(event) {
console.log(event.request.url);
if (event.request.url.contains('/bulmaswatch/')) {
return localforage.getItem('theme')
.then(function(theme) {
if (theme === 'kb-dark-theme') {
let darkThemeRequest = new Request(request.url.replace('bulmaswatch/default/', 'bulmaswatch/superhero/'), {
method: request.method,
headers: request.headers,
mode: 'same-origin',
credentials: request.credentials,
redirect: 'manual'
});
return fetch(darkThemeRequest);
}
return fetch(event.request);
})
}
});
// Log SW installation
this.addEventListener('install', function(event) {
console.log('[SW]: installing....');
});
// Log SW activation
this.addEventListener('activate', function activator(event) {
console.log('[SW]: activate!');
});
在 chrome 中调试时(和 chrome canary,因为我听说那里有更好的 service worker 调试支持),fetch
甚至从未调用过回调。没有记录任何请求。
我确实看到服务人员在 chrome 的开发工具中注册并处于活动状态。我看到控制台中记录了其他事件。
此外,当调试并在脚本开头放置断点时,看起来好像bulmaswatch.min.css
已经获取了。
知道我错过了什么吗?:-)
谢谢
解决方案
根本问题与您的服务人员的范围有关。
当我访问https://thatkookooguy.github.io/postmortem-demo/postmortem/002并查看 Chrome 的 DevTools 中的 Application > Service Workers 面板时,我看到 service worker 有一个范围https://thatkookooguy.github.io/postmortem-demo/assets
并且不控制任何客户端。
如果您将sw.js
文件移出/assets/
子目录,并移至站点的顶级目录(即/postmortem-demo/
),然后切换您的注册码以反映这一点,那么您的服务工作者应该能够控制您的客户端页面:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/postmortem-demo/sw.js');
}
(这意味着在本地开发时,您还应该使用 URL 前缀为您的 Web 应用程序提供/postmortem-demo/
匹配的 URL。)
以下资源包含有关 Service Worker 范围的更多信息:
推荐阅读
- python - 在具有活动 virtualenv 的 python 模块上使用 vscode 调试器,launch.json 中的“配置文件中的 python 路径无效”
- excel - VBA 代码仅在我逐步运行时才有效(F8)
- reactjs - SCORM 加载资源失败:服务器响应状态为 404 ()
- python - 是否可以自动验证 Python 类型存根包?
- python - 了解 PyTorch 中的反向传播
- blogger - 博主太日期标题问题
- angular - 当有多个组件时,Angular 服务被调用两次
- php - 终端命令删除多个文件-CPanel,共享主机感染病毒
- redirect - 将 Strapi 管理员索引重定向到管理员登录
- javascript - 查找 HTML 文档中任意位置的两个元素在 DOM 中的相对位置