Service Worker 响应时间慢

Service Worker slow response times

在 Windows 和 Android Google Chrome 浏览器中,service worker 的响应时间 Google Chrome =18=] 当您使用带有以下选项的 Cache.match() 函数时,存储在该特定 缓存存储 中的项目数量呈线性增加;

ignoreSearch = true

在多个缓存中划分项目会有所帮助,但这样做并不总是很方便。此外,即使存储的物品数量有少量增加,也会在响应时间上产生很大差异。根据我的测量,缓存中的项目数量每增加十倍,响应时间大约会增加一倍。

我的 question in chromium issue tracker 的官方回答显示该问题是 Chrome 中缓存存储实现的一个已知性能问题,只有当您将 Cache.match()ignoreSearch 一起使用时才会发生参数设置为 true.

如您所知,ignoreSearch 用于在将请求与缓存中的响应进行匹配时忽略 URL 中的查询参数。 Quote from MDN:

...whether to ignore the query string in the url. For example, if set to true the ?value=bar part of http://example.com/?value=bar would be ignored when performing a match.

由于停止使用查询参数匹配并不是很方便,因此我想出了以下解决方法,并将其张贴在这里,希望能为大家节省时间;

// if the request has query parameters, `hasQuery` will be set to `true`
var hasQuery = event.request.url.indexOf('?') != -1;

event.respondWith(
  caches.match(event.request, {
    // ignore query section of the URL based on our variable
    ignoreSearch: hasQuery,
  })
  .then(function(response) {
    // handle the response
  })
);

这很好用,因为它可以正确处理每个请求 一个查询参数,同时处理其他请求仍然以闪电般的速度。而且您无需更改应用程序中的任何其他内容。

根据 guy in that bug report,问题与缓存中的项目数有关。我做了一个解决方案并将其发挥到极致,为每个资源提供自己的缓存:

var cachedUrls = [
    /* CACHE INJECT FROM GULP */
];

//update the cache
//don't worry Whosebug, I call this only when the site tells the SW to update
function fetchCache() {
    return Promise.all(
        //for all urls
        cachedUrls.map(function(url) {
            //add a cache
            return caches.open('resource:'url).then(function(cache) {
                //add the url
                return cache.add(url);
            });
        });
    );
}

在我们这里的项目中,静态资源设置了高缓存过期,我们使用查询参数(存储库修订号,注入 html)仅作为管理 [浏览器]缓存。
使用您的解决方案来选择性地使用 ignoreSearch 并没有真正起作用,因为无论如何我们都必须将它用于所有静态资源,以便我们可以获得缓存命中!

然而,我不仅不喜欢这个 hack,而且它仍然执行得非常慢。


好吧,鉴于这只是我需要 ignoreSearch 的一组特定资源,我决定采取不同的路线;
只需手动从 url 请求中删除参数,而不是依赖 ignoreSearch.

self.addEventListener('fetch', function(event) {
    //find urls that only have numbers as parameters
    //yours will obviously differ, my queries to ignore were just repo revisions
    var shaved = event.request.url.match(/^([^?]*)[?]\d+$/);
    //extract the url without the query
    shaved = shaved && shaved[1];

    event.respondWith(
        //try to get the url from the cache.
        //if this is a resource, use the shaved url,
        //otherwise use the original request
        //(I assume it [can] contain post-data and stuff)
        caches.match(shaved || event.request).then(function(response) {
            //respond
            return response || fetch(event.request);
        })
    );
});

我遇到了同样的问题,之前的方法导致一些请求错误,应该是 ignoreSearch:false。一种对我有用的简单方法是通过使用 url.contains('A') &&[= 将 ignoreSearch:true 简单地应用于某些请求16=] ... 请参见下面的示例:

    self.addEventListener("fetch", function(event) {
         
      var ignore
    
      if(event.request.url.includes('A') && event.request.url.includes('B') && event.request.url.includes('C')){
        ignore = true
      }else{
        ignore = false
      }
      event.respondWith(
        caches.match(event.request,{
            ignoreSearch:ignore, 
          })
          .then(function(cached) {
            ...
           }