我如何在 service worker fetch 中检测到请求是针对清单的 start_url?

How do I detect in a service worker fetch that the request is for the manifest's start_url?

我有一个 PWA,它有一个 manifest.json with a 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的值是被请求的相对路由。

我可以在 SW 中加载 manifest.json,但感觉真的很笨重。我可以在 SW 中对值进行硬编码,但是如果配置发生变化,我需要更新两个地方。

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

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

所以...

我已经想出了如何做到这一点,但它很讨厌,我相信有更好的方法。

特别是我 hard-coding 在清单内联中(我可以 fetch 它,但这也很讨厌)。

const manifest = { start_url: 'appshell' };

然后我用self.location获取service worker的路径。这包括文件名,所以我 trim 最后:

// 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 而无需缓存其他所有内容,因此这是目前公认的答案。我很想看到一个更好的方法来做到这一点,理想情况下没有困难 coding/fetching manifest.json 这样配置更改就不需要新的服务工作者了。