首页 文章

服务工作者离线支持与pushstate和客户端路由

提问于
浏览
2

我正在使用服务工作者为我的单页Web应用程序引入脱机功能 . 它非常简单 - 在可用时使用网络,或者如果不是,则尝试从缓存中获取:

服务worker.js:

self.addEventListener("fetch", event => {
    if(event.request.method !== "GET") {
        return;
    }
    event.respondWith(
        fetch(event.request)
            .then(networkResponse => {
                var responseClone = networkResponse.clone();
                if (networkResponse.status == 200) {
                    caches.open("mycache").then(cache => cache.put(event.request, responseClone));
                }
            return networkResponse;
        })
        .catch(_ => {
            return caches.match(event.request);
        })
    )
})

因此它拦截所有GET请求并缓存它们以供将来使用,包括初始页面加载 .

在DevTools中切换到“离线”并在应用程序的根目录刷新按预期工作 .

但是,我的应用程序使用HTML5 pushstate和客户端路由器 . 用户可以导航到新路线,然后离线,然后点击刷新,并且将获得“无互联网”消息,因为服务工作者从未被告知过这个新URL .

我想不出办法解决它 . 与大多数SPA一样,我的服务器配置为index.html提供许多全能URL . 我需要为服务工作者提供某种类似的行为 .

1 回答

  • 4

    fetch 处理程序中,您需要检查 event.request.mode 是否设置为 'navigate' . 如果是这样,它是一个导航,而不是使用与特定URL匹配的缓存响应进行响应,您可以使用 index.html 的缓存响应进行响应 . (或 app-shell.html ,或您用于SPA的通用HTML的任何URL . )

    您更新的 fetch 处理程序看起来大致如下:

    self.addEventListener('fetch', event => {
      if (event.request.method !== 'GET') {
        return;
      }
    
      if (event.request.mode === 'navigate') {
        event.respondWith(caches.match('index.html'));
        return;
      }
    
      // The rest of your fetch handler logic goes here.
    });
    

    这是服务工作者的常见用例,如果您更喜欢使用预打包的解决方案,workbox-routing module中的NavigationRoute class可以为您自动执行 .

相关问题