用 fetch 事件替换 service worker 中的资产
replace asset in service worker with fetch event
我正在尝试与我的服务人员热切换主题样式表。
我为 Jekyll 创建了一个主题(与 GitHub 页面一起使用),并希望能够在深色主题和浅色主题 ("turn off the lights") 之间进行替换并使其保持一致。
现在,这是通过将状态保存到 localstorage
并根据该状态替换主题 link
元素来实现的。
问题是,检查发生在获取原始白色主题之后,因此即使 localstorage
设置了深色主题,用户也会看到白色主题的闪烁
这是它目前的行为方式(按钮在右上角):
https://thatkookooguy.github.io/postmortem-demo/postmortem/002
after changing the theme, try navigating to another page. the page loads with the white theme, and after that changes to the dark theme
我想我可以通过在 service worker 中切换脚本来解决这个问题,因为我可以 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');
}
(这意味着在本地开发时,您还应该使用 /postmortem-demo/
的 URL 前缀来提供您的 Web 应用程序以匹配它。)
以下资源包含有关服务工作者范围的更多信息:
我正在尝试与我的服务人员热切换主题样式表。
我为 Jekyll 创建了一个主题(与 GitHub 页面一起使用),并希望能够在深色主题和浅色主题 ("turn off the lights") 之间进行替换并使其保持一致。
现在,这是通过将状态保存到 localstorage
并根据该状态替换主题 link
元素来实现的。
问题是,检查发生在获取原始白色主题之后,因此即使 localstorage
设置了深色主题,用户也会看到白色主题的闪烁
这是它目前的行为方式(按钮在右上角): https://thatkookooguy.github.io/postmortem-demo/postmortem/002
after changing the theme, try navigating to another page. the page loads with the white theme, and after that changes to the dark theme
我想我可以通过在 service worker 中切换脚本来解决这个问题,因为我可以 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');
}
(这意味着在本地开发时,您还应该使用 /postmortem-demo/
的 URL 前缀来提供您的 Web 应用程序以匹配它。)
以下资源包含有关服务工作者范围的更多信息: