首页 > 解决方案 > 如何在服务工作者获取中检测到请求是针对清单的 start_url 的?

问题描述

我有一个 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- 所以,例如,我可能有:

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

所以...

标签: javascriptservice-workerprogressive-web-appsfetch-api

解决方案


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

特别是我在清单内联中进行了硬编码(我可以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这样配置更改就不需要新的服务人员。


推荐阅读