You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Service Worker拦截主题样式表时Fetch事件未触发

解决Service Worker拦截样式请求失败&主题闪烁问题

咱们一步一步拆解你遇到的问题,核心是三个关键点导致fetch事件没触发,以及初始闪烁的优化方案:

1. Service Worker作用域不匹配(最关键的原因)

你注册SW的路径是{{ site.baseurl }}/assets/sw.js,默认情况下,Service Worker的作用域是它所在的目录(也就是/assets/)。这意味着它只能控制路径以/assets/开头的页面和请求,而你的页面在/postmortem/002这类非/assets/路径下,完全不在SW的控制范围内,自然不会触发fetch事件。

修复方案:
注册SW时显式指定作用域为站点根路径(覆盖所有页面):

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('{{ site.baseurl }}/assets/sw.js', {
    scope: '{{ site.baseurl }}/' // 确保作用域覆盖整个站点
  }).then(function() {
    console.log("Service Worker Registered");
  });
}

2. Fetch事件回调的代码错误

你的SW代码里有两处致命错误,导致即使触发了fetch事件也无法正常工作:

  • 字符串判断包含应该用includes(),不是contains()(contains()是DOM元素的方法,字符串没有这个API)
  • 创建新Request时用了未定义的request变量,应该是event.request
  • 必须调用event.respondWith()告诉SW你要接管这个请求的响应,否则SW会直接走默认请求流程

修正后的fetch事件代码:

this.addEventListener('fetch', function(event) {
  console.log(event.request.url);
  if (event.request.url.includes('/bulmaswatch/')) {
    // 必须调用event.respondWith来接管响应逻辑
    event.respondWith(
      localforage.getItem('theme')
        .then(function(theme) {
          if (theme === 'kb-dark-theme') {
            const darkThemeUrl = event.request.url.replace('bulmaswatch/default/', 'bulmaswatch/superhero/');
            const darkThemeRequest = new Request(darkThemeUrl, {
              method: event.request.method,
              headers: event.request.headers,
              mode: event.request.mode, // 保留原请求的mode,不要硬写same-origin(跨域请求mode是cors)
              credentials: event.request.credentials,
              redirect: event.request.redirect
            });
            return fetch(darkThemeRequest);
          }
          return fetch(event.request);
        })
    );
  }
});

3. Prefetch资源的加载时机不对

你给bulma样式加了rel="stylesheet prefetch",prefetch是浏览器在页面加载完成后空闲时预取资源,用于未来导航,不是当前页面立即使用的资源。这会导致当前页面的样式加载请求可能在SW激活前就完成了,或者根本不会触发SW的fetch拦截。

修复方案:
把link标签的rel改成普通的stylesheet,确保样式是当前页面的关键资源,会被SW拦截:

<link id="bulma-theme" rel="stylesheet" href="//unpkg.com/bulmaswatch/default/bulmaswatch.min.css">

额外优化:彻底避免初始闪烁

即使SW配置正确,第一次加载页面时SW可能还没完成激活,还是会出现白色闪烁。可以在<head>里加一段内联脚本,在样式表加载前就读取主题状态并修改href:

<script>
  // 内联脚本会在页面解析时立即执行,比外部脚本和SW更早
  const savedTheme = localStorage.getItem('theme') || 'default';
  const themeLink = document.getElementById('bulma-theme');
  if (savedTheme === 'kb-dark-theme') {
    themeLink.href = themeLink.href.replace('bulmaswatch/default/', 'bulmaswatch/superhero/');
  }

  // 再注册SW
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('{{ site.baseurl }}/assets/sw.js', {
      scope: '{{ site.baseurl }}/'
    }).then(function() {
      console.log("Service Worker Registered");
    });
  }
</script>

按照以上步骤修改后,SW的fetch事件应该能正常触发,主题切换的闪烁问题也能彻底解决。

内容的提问来源于stack exchange,提问作者Thatkookooguy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:02:29