Service Worker:cache.match(request)返回undefined

时间:2017-03-15 15:06:17

标签: javascript caching service-worker

我有一个简单的服务工作者,它将两个资源(index.html,app.js)添加到缓存中(在安装时),删除旧缓存(在激活时)并从缓存中提供资源(如果存在),否则从网络(取回)。要使新服务工作者注册并删除旧缓存,我会使用每个新资源版本增加CACHE_NAME中的版本号:

var CACHE_NAME = 'test-cache-v4';
var urlsToCache = ['./','./app.js'];

self.addEventListener('install', function (event) {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function (cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
  return self.skipWaiting();
});

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (key !== CACHE_NAME) {
          return caches.delete(key);
        }
      }));
    }) 
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open(CACHE_NAME).then(function(cache){
      return cache.match(event.request)
        .then(function(response) {
          if (response) {
          console.log('SERVED FROM CACHE');
            return response;
          }
          return fetch(event.request).then(function(response){
              console.log('Response from network is:', response);
              return response;
          });
        }
      )
    })
  );
});

在我的本地主机上,服务工作者完全正常。

但是在服务器上由

返回的响应/承诺
return cache.match(event.request)

总是未定义。因此,资源永远不会从缓存中提供,而是始终来自网络。

即使在Chrome的开发工具“应用程序”选项卡中,我也可以看到新服务工作者的注册工作正常,“缓存存储”充满了我的新缓存资源(请求URL到index.html和app.js) )。我还认为我已经使用Cache-Control no-cache正确处理了Web服务器配置调整。

如果我改变

return cache.match(event.request)

return cache.match(event.request.url)

服务工作者也可以在服务器上工作。

但是,我想理解为什么我能找到的所有示例中使用的语法在我可以找到的所有示例中都使用。

一个区别是我通过https直接访问localhost和服务器。

编辑:另一个区别是来自服务器的资源被压缩(Header => content-encoding:gzip)。

是否可以将其与其中一种差异联系起来?

非常感谢任何想法!

2 个答案:

答案 0 :(得分:2)

我遇到了完全相同的问题:gzip压缩,使用https的服务器,本地主机上的本地

TL; DR:

return cache.match(event.request, {ignoreVary: true})  // set option `ignoreVary` to `true`

完整版本:

在此页面Cache.match() - Web APIs | MDN上,我找到了一个选项ignoreVary

ignoreVary:一个布尔值,当设置为true时,它指示匹配操作不执行VARY标头匹配-即,如果URL匹配,则无论Response对象是否具有VARY标头,您都将获得匹配。默认为false。

我检查了请求的响应,它确实有一个值为Vary的{​​{1}}字段。尽管每次我请求时此字段的值都不会更改,但缓存不会匹配。

因此解决方案是将Cookie, Accept-Language添加到您的{ignoreVary: true}

答案 1 :(得分:0)

1。无缓存

尝试取消服务器中的缓存机制,我在远程Apache服务器中找到这些代码(通过HTTPS提供):

<filesMatch "\.(html|htm|js|css)$">
    FileETag None
    <ifModule mod_headers.c>
        Header unset ETag
        Header append Vary User-Agent env=!dont-vary
        Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
        Header set Pragma "no-cache"
        Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
    </ifModule>
</filesMatch>

我的localhost不是通过HTTPS和示例提供的 How to Setup a Basic Service Worker可以正常使用。

2。匹配方法

Cache.match() - Web APIs | MDN表明该参数应该是您尝试在缓存中找到的请求。但cache.match(event.request.url)在localhost和远程Apache Server中也可以正常工作。缓存没有问题。

3。 gzip的

在localhost(没有gzip)和远程Apache服务器(gzip)中测试之后,两个缓存文件都没有任何错误。所以gzip不是其中一个原因。