如何在服务工作者中检测到请求是针对清单的start_url的?

时间:2019-04-10 11:34:13

标签: javascript service-worker progressive-web-apps fetch-api

我有一个PWA,其中有一个manifest.json和一个start_url

我有一个带有fetch事件的服务工作者,该事件仅缓存某些请求。 在服务工作者中,这是通过覆盖对缓存中代理的响应(为清楚起见,使用TypeScript)完成的:

self.addEventListener('fetch', (event: FetchEvent) => {
    // This MUST be synchronous until respondWith is called

    const cache = isCachable(event.request);
    if (!isCachable)
        return; // Don't proxy, let the network request continue

    // Kick off a promise to check the cache, and clone/cache the response otherwise
    const proxy: Promise<Response> = cacheResponse(event);

    event.respondWith(proxy);
}

我想缓存start_url,这意味着上面的isCachable必须能够知道start_url的值是所请求的相对路由。

我可以在软件中加载manifest.json,但这确实很笨拙。我可以在SW中对值进行硬编码,但是如果配置更改,则需要更新两个位置。

fetch处理程序中,event.request.url是绝对的,但是start_url是相对于manifest.json的-因此,例如,我可能有:

  • manifest.json{ "start_url": "appshell" ... }
  • 网站已部署到www.example.com/folder/(但可能已部署到sub.example.comwww.example.com/a/b或其他任何东西)
  • 在线用户访问网站,要么访问所有内容,要么直接安装脚本缓存。
  • 稍后,同一用户离线访问。
  • 上面的抓取操作以event.request.url === 'www.example.com/folder/appshell'触发
  • 我需要isCachable函数来告知应该同步缓存资源。它需要确定www.example.com/folder/appshellappshell(解析相对链接)并且将appshell设置为start_url(读取清单)。

很显然,所有这些 都可以进行硬编码。但是,每个PWA都需要start_url的缓存响应,因此这不是一个新问题。在我重新发明轮子之前,有没有更好的方法或缺少的东西?

所以...

  • 鉴于服务工作人员需要清单,是否有很好的方法在工作人员中获取清单的配置?
  • 有没有办法解决与清单比较的相对链接?

1 个答案:

答案 0 :(得分:0)

我已经找到了解决方法,但这很讨厌,我敢肯定有更好的方法。

尤其是我正在清单内联中进行硬编码(我可以fetch,但这也很讨厌)。

const manifest = { start_url: 'appshell' };

然后,我使用self.location来获取服务人员的路径。这包括文件名,所以我将其修剪掉:

// if file is 'sw.js' that's 5 chars off the end
const applicationRoot = new URL(self.location.href.slice(0, -5) + manifest.start_url); 

然后我可以对此进行检查:

self.addEventListener('fetch', (event: FetchEvent) => {
    // This MUST be synchronous until respondWith is called

    const url = new URL(event.request.url);
    if (url.pathname === applicationRoot.pathname) {
        // Request is for the start_url, always return something so the PWA starts offline
        event.respondWith(...):
    }

    // ... see question for rest
});

这很笨拙,但是至少它可以始终为缓存的start_url提供服务而无需缓存其他所有内容,因此,这是目前公认的答案。我希望看到一种更好的方法,理想情况下无需进行硬编码/获取manifest.json,以便在那里进行配置更改不需要新的服务人员。