服务工作者 - 网络优先,然后缓存并回退到静态页面

11

我希望在我的网站上增加服务工作者以为我的用户提供良好的离线体验。(网站后端使用PHP)

我对JavaScript Promise和Service Worker还不是很熟悉,但我已经做到了这一步:

我的index.php页面有以下脚本来注册Service Worker:

<script> 
    if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js')};
</script>

并且对于服务工作者文件,我使用以下代码

var CACHE_STATIC_NAME = 'static-v74';
var CACHE_DYNAMIC_NAME = 'dynamic-v74';

self.addEventListener('install', function (event) {
  console.log('Installing Service Worker ...', event);
  event.waitUntil(
    caches.open(CACHE_STATIC_NAME)
      .then(function (cache) {
        console.log('Precaching App Shell');
        cache.addAll([
          'offline.php', // offline page
          'assets/bundle.css',
          'assets/bundle.js',
          'assets/images/logo.jpg',
          'assets/images/favicon.ico'
        ]);
      })
  )
});

self.addEventListener('activate', function (event) {
  console.log('Activating Service Worker ....', event);
  event.waitUntil(
    caches.keys()
      .then(function (keyList) {
        return Promise.all(keyList.map(function (key) {
          if (key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
            console.log('Removing old cache.', key);
            return caches.delete(key);
          }
        }));
      })
  );
  return self.clients.claim();
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    // Try the network
    fetch(event.request)
      .then(function(res) {
        return caches.open(CACHE_DYNAMIC_NAME)
          .then(function(cache) {
            // Put in cache if succeeds
            cache.put(event.request.url, res.clone());
            return res;
          })
      })
      .catch(function(err) {
          // Fallback to cache
          return caches.match(event.request);
      })
  );
});

实际上,这段代码按照预期正常工作:

(1) 它注册了服务工作者并获取了我的静态缓存文件的副本。 (2) 当激活新的服务工作者时,它会删除旧的缓存。 (3) 在每个新请求中,它首先从网络中获取,如果成功,就会将请求的新副本放入缓存中。 (4) 如果在离线状态下无法进行网络请求,则会向用户返回上次网络请求的新副本。

我想要实现的是(如果用户处于离线状态并尝试请求未在缓存中的新页面,他应该被重定向到保存在静态缓存中的(offline.php)页面)如下所示

// If both (network & cache) fail, show a generic fallback:
return caches.match('offline.php');

但是我有一个问题,就是我不知道在我的(sw.js)文件中的(fetch)步骤中应该在哪里添加这一行,我真的尝试了阅读更多关于服务工作者和JavaScript承诺的内容,并尝试在代码的不同位置多次添加此行,但每次都无法使其正常工作,反而搞砸了先前的情况或保持现状但无法实现此目标。

非常感谢您的帮助和提前致谢。


另外请参见 缓存策略离线手册缓存策略概述 - djvg
1个回答

16

在你的fetch事件侦听器中:

.catch(function(err) {
      // Fallback to cache
      return caches.match(event.request);
  })

caches.match(event.request)实际上返回一个Promise,如果在缓存中没有找到匹配项,则解析为undefined。

检查undefined并从缓存返回offline.php:

Original Answer:
``` if (response === undefined) { return caches.match('offline.php'); } ```
return caches.match(event.request)
  .then(function(res){
    if (res === undefined) { 
      // get and return the offline page
    } 
    return res;
})

谢谢,你的代码 res === undefined 今天救了我。 - Dedi Ananto

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