为不受支持的浏览器实现带有应用缓存回退的服务工作者

Implementing Service Workers with an appcache fallback for unsupported browsers

我正在研究在 Aurelia 中构建渐进式 Web 应用程序的技术,该应用程序具有适用于主要浏览器的离线功能。 Service Workers 似乎是资产缓存的首选,但在 Safari(以及当前的 Edge)中缺乏支持。如果不支持,是否可以使用 service workers 回退到 appcache?如果安装了应用程序缓存清单和服务工作者,应用程序将如何运行?

检查浏览器支持的技术很容易:

if(navigator.serviceWorker){
    initServiceWorker()
}else if(window.applicationCache){
    initApplicationCache();
}else{
    console.log('no caching possible');
}

Service Worker 的动态加载应该不是问题,因为无论如何它都是在 javascript 中完成的。

动态加载 applicationCache 的 mainfest 似乎不可能,但您可以尝试 iframe hack,请参阅: Dynamically Trigger HTML5 Cache Manifest file?

如果浏览器支持服务工作者,则将使用服务工作者缓存而不是 appCache 清单。您可以包含 Safari 等旧版浏览器的 appCache 清单,一切都会像过去一样工作。此外,对于现代浏览器,它们将利用 service worker 缓存并表现得好像 appCache 不存在一样。有点像响应式图片的工作方式。

现在是 2019 年了,iPhone 仍然无法让 Service Worker 在 WebView 中正常运行。所以应用程序缓存回退仍然有用。

当 service worker 启动时,应用程序缓存不会有任何影响,这并不完全正确。它仍然试图更新它的缓存,这是一件愚蠢的事情。关闭它并不重要,但会是一件好事。

我现在在 service worker 运行时禁用应用程序缓存的技巧是拦截 html(导航)请求并从 [=12= 中删除 manifest 属性].

Service Worker 脚本中的类似内容:

self.addEventListener('fetch', (ev) => {
  if (request.mode === 'navigate' && request.method === 'GET') {
    ev.respondWith(
      fetch(ev.request.url)
        .then(r => r.text())
        .then(html => new Response(html.replace('manifest=', 'xmanifest='), {
          headers: {'Content-Type': 'text/html'}
        }))
    )
  }
})