web-dev-qa-db-ja.com

Service Worker-最初にネットワーク、次に静的ページへのフォールバックでキャッシュ

自分のサイトにServiceWorkerを追加して、サイトユーザーに優れたオフラインエクスペリエンスを提供したいと考えています。 (サイトのバックエンドはPHPです)

私はまだJavascriptPromiseとServiceWorkerに慣れていませんが、これまでに到達したことは次のとおりです。

私のindex.phpページにはServiceWorkerを登録するためのこのスクリプトがあります

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

およびServiceWorkerファイルの場合次のコードを使用します

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)Service Workerを登録し、静的キャッシュファイルのコピーを取ります。 (2)新しいService Workerをアクティブ化すると、古いキャッシュが削除されます。 (3)新しいリクエストがあるたびに、最初にネットワークからフェッチし、成功した場合は、リクエストの新しいコピーをキャッシュに入れます。 (4)オフライン時にネットワーク要求を行うことができなかった場合、最後のネットワーク要求の新しいコピーをユーザーに返します。

私が彼女に達成したいのは(ユーザーがオフラインの場合、キャッシュにない新しいページをリクエストしようとすると、静的キャッシュに保存された(offline.php)ページにリダイレクトされるはずです)- 次のように

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

しかし、(フェッチ)ステップ内の(sw.js)ファイルのどこにこの行を追加する必要があるのか​​正確にわからないという問題があります。実際にサービスワーカーとJavascriptの約束についてもっと読んで、この行を数回追加してみました私のコードの別の場所ですが、毎回それを機能させることはできませんが、前のシナリオを見逃すか、シナリオを維持しますが、この目標を達成できません。

よろしくお願いします。よろしくお願いします。

6
Ramy Ahmed

フェッチイベントリスナーの場合:

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

caches.match(event.request)は、実際には、キャッシュから一致するものが見つからない場合に未定義に解決されるPromiseを返します。

未定義をチェックし、キャッシュからoffline.phpを返します。

return caches.match(event.request)
  .then(function(res){
    if (res === undefined) { 
      // get and return the offline page
    } 
    return res;
})
13
pate