使用fetch事件替换service worker中的资产

时间:2018-05-16 11:35:01

标签: javascript html service-worker interceptor service-worker-events

我正在尝试用我的服务工作者热切换主题样式表。

我为Jekyll创建了一个主题(与GitHub页面一起使用),并希望能够在黑暗主题和灯光主题(“关闭灯光”)之间进行替换,并使其保持一致。

现在,这可以通过将状态保存到localstorage并根据该替换主题link元素来实现。

问题是,在获取原始白色主题后检查发生,因此即使localstorage设置了黑暗主题,用户也会看到白色主题的闪光

这是它目前的行为方式(按钮位于右上角): https://thatkookooguy.github.io/postmortem-demo/postmortem/002

  

更改主题后,尝试导航到其他页面。页面加载白色主题,然后更改为黑暗主题

我以为我可以通过在服务工作者中切换脚本来解决这个问题,因为我可以addEventListenerfetch事件并用另一个提取替换在promise链中。

但代码似乎不起作用。如果我在事件回调中添加一个调试点,它永远不会被触发(不是资产而不是实际的页面提取)

HTML Head

<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中调试,因为我听说有更好的服务工作者调试支持),fetch上的回调甚至从未调用过。没有记录任何请求。

我确实看到服务工作者在chrome的开发工具中注册并处于活动状态。 我看到其他事件在控制台中登录。

此外,在脚本开头调试并设置断点时,看起来已经提取了bulmaswatch.min.css

知道我缺少什么吗? : - )

感谢

1 个答案:

答案 0 :(得分:1)

潜在问题与服务工作者的范围有关。

当我访问https://thatkookooguy.github.io/postmortem-demo/postmortem/002并查看应用程序&gt; Chrome的DevTools中的Service Workers面板,我看到服务工作者的范围为https://thatkookooguy.github.io/postmortem-demo/assets,并且不控制任何客户端。

Screenshot of Application panel

如果您将sw.js文件移出/assets/子目录,并进入您网站的顶级目录(/postmortem-demo/),然后将注册码转换为反映一下,那么你的服务工作者应该能够控制你的客户页面:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/postmortem-demo/sw.js');
}

(这意味着在本地开发时,您还应该使用网址前缀/postmortem-demo/来为您的网络应用提供服务,以便与之匹配。)

以下资源提供了有关服务工作者范围的更多信息: