web-dev-qa-db-ja.com

Service Workerでオフライン状態を検出するためのベストプラクティス

クライアントにネットワーク接続がない場合に表示されるoffline.htmlページをキャッシュすることになっているサービスワーカーがいます。ただし、ナビゲーターがオフラインになっていてもオフラインになっていると考える場合があります。つまり、navigator.onLine === falseです。これは、ユーザーがオンラインであっても実際のコンテンツの代わりにoffline.htmlを受け取る可能性があることを意味します。これは明らかに避けたいことです。

これは、main.jsでサービスワーカーを登録する方法です。

// Install service worker for offline use and caching
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {scope: '/'});
}

私の現在のservice-worker.js

const OFFLINE_URL = '/mysite/offline';
const CACHE_NAME = 'mysite-static-v1';

self.addEventListener('install', (event) => {
  event.waitUntil(
    // Cache the offline page when installing the service worker
    fetch(OFFLINE_URL, { credentials: 'include' }).then(response =>
      caches.open(CACHE_NAME).then(cache => cache.put(OFFLINE_URL, response)),
    ),
  );
});

self.addEventListener('fetch', (event) => {
  const requestURL = new URL(event.request.url);

  if (requestURL.Origin === location.Origin) {
    // Load static assets from cache if network is down
    if (/\.(css|js|woff|woff2|ttf|eot|svg)$/.test(requestURL.pathname)) {
      event.respondWith(
        caches.open(CACHE_NAME).then(cache =>
          caches.match(event.request).then((result) => {
            if (navigator.onLine === false) {
              // We are offline so return the cached version immediately, null or not.
              return result;
            }
            // We are online so let's run the request to make sure our content
            // is up-to-date.
            return fetch(event.request).then((response) => {
              // Save the result to cache for later use.
              cache.put(event.request, response.clone());
              return response;
            });
          }),
        ),
      );
      return;
    }
  }

  if (event.request.mode === 'navigate' && navigator.onLine === false) {
    // Uh-oh, we navigated to a page while offline. Let's show our default page.
    event.respondWith(caches.match(OFFLINE_URL));
    return;
  }

  // Passthrough for everything else
  event.respondWith(fetch(event.request));
});

私は何を間違えていますか?

16
Kaivosukeltaja

_navigator.onLine_および関連するイベントは、UIを更新してオフラインであることを示し、たとえばキャッシュに存在するコンテンツのみを表示する場合に役立ちます。

ただし、_navigator.onLine_のチェックに依存するService Workerロジックを記述することは避けたいと思います。代わりに、fetch()を無条件に作成し、失敗した場合はバックアップ応答を提供してください。これにより、オフライン、 lie-fi 、またはWebサーバーの問題が原因でfetch()が失敗するかどうかに関係なく、Webアプリが期待どおりに動作するようになります。

_// Other fetch handler code...

if (event.request.mode === 'navigate') {
  return event.respondWith(
    fetch(event.request).catch(() => caches.match(OFFLINE_URL))
  );
}

// Other fetch handler code...
_
13
Jeff Posnick