Service Worker响应速度慢

11
在Windows和Android Google Chrome浏览器中(还未测试其他浏览器),当您使用具有以下选项的Cache.match()函数时,服务工作线程响应时间与特定缓存存储中存储的项目数量呈线性增长。
ignoreSearch = true

将项目分配到多个缓存中有所帮助,但不总是方便的。而且,即使存储的项目数量增加了很少一部分,在响应时间上也会有很大的差异。根据我的测量,每当缓存中的项目数量增加十倍时,响应时间大约会增加一倍。

3个回答

14

官方回答我的Chromium问题追踪器中的问题揭示了Cache Storage在Chrome中实现性能存在已知问题,只有当您使用Cache.match()并将ignoreSearch参数设置为true时才会发生该问题。

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

...是否要忽略url中的查询字符串。例如,如果将其设置为true,则在进行匹配时,http://example.com/?value=bar中的?value=bar部分将被忽略。

由于停止使用查询参数匹配并不是很方便,因此我想出了以下解决方法,并在此发布,希望它能为某些人节省时间;

// 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
  })
);

这非常有效,因为它可以正确地处理每个带有查询参数的请求,并仍然以惊人的速度处理其他请求。您无需更改应用程序中的任何其他内容。


太棒了!!!希望你能完成event.respondWith()的代码。 - Mahmoud Kassem
2
@MahmoudAliKassem 当然,这是你需要的。我更新了代码片段,现在它可以完整地工作了。干杯! - Umur Karagöz

1

我曾经遇到同样的问题,之前的解决方法会导致一些请求出现错误,这些请求应该是 ignoreSearch:false。一个对我有效的简单方法是通过使用 url.contains('A') &&ignoreSearch:true 应用于特定的请求。参见下面的示例:

    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) {
            ...
           }

1
根据该错误报告中的那个人所说,问题与缓存中的项目数量有关。我提出了一个解决方案并将其推到了极致,为每个资源分配了自己的缓存。
var cachedUrls = [
    /* CACHE INJECT FROM GULP */
];

//update the cache
//don't worry StackOverflow, 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);
        })
    );
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接