web-dev-qa-db-ja.com

プログレッシブウェブアプリ:接続が再び確立したときに検出して処理する方法

PWAを使用すると、デバイス接続がオフラインモードでダウンした場合に処理できます。しかし、どのようにして固定ネットワーク接続を検出し、アプリケーションを自動的にリロード/再アクティブ化するのでしょうか?

14
Hank Phung

offlineおよびonlineイベント を監視できます。これらは 広くサポートされています です。さらに、ターゲットサーバーのURLからHEADをフェッチして、接続をテストできます。

// Test this by running the code snippet below and then
// use the "Offline" checkbox in DevTools Network panel

window.addEventListener('online', handleConnection);
window.addEventListener('offline', handleConnection);

function handleConnection() {
  if (navigator.onLine) {
    isReachable(getServerUrl()).then(function(online) {
      if (online) {
        // handle online status
        console.log('online');
      } else {
        console.log('no connectivity');
      }
    });
  } else {
    // handle offline status
    console.log('offline');
  }
}

function isReachable(url) {
  /**
   * Note: fetch() still "succeeds" for 404s on subdirectories,
   * which is ok when only testing for domain reachability.
   *
   * Example:
   *   https://google.com/noexist does not throw
   *   https://noexist.com/noexist does throw
   */
  return fetch(url, { method: 'HEAD', mode: 'no-cors' })
    .then(function(resp) {
      return resp && (resp.ok || resp.type === 'opaque');
    })
    .catch(function(err) {
      console.warn('[conn test failure]:', err);
    });
}

function getServerUrl() {
  return document.getElementById('serverUrl').value || window.location.Origin;
}
<fieldset>
  <label>
    <span>Server URL for connectivity test:</span>
    <input id="serverUrl" style="width: 100%">
  </label>
</fieldset>
<script>document.getElementById('serverUrl').value = window.location.Origin;</script>

<p>
  <i>Use Network Panel in DevTools to toggle Offline status</i>
</p>

これを処理する1つの technique

  • オフラインイベント

    • オフラインアイコン/ステータスを表示
    • (キャッシュされたデータを介して)オフラインで利用できる機能のみを有効にする
  • オンラインイベント

    • オンラインアイコン/ステータスを表示
    • すべての機能を有効にする
38
tony19

接続されている場合にのみデバイスに通知するonlineイベントに注意してください。実際のインターネット接続なしで(たとえば、資格情報のため)WiFiホットスポットに接続できます。

18
Nicolas Hoizey

PWAでの一般的な方法は、アプリケーションに対して Application Shell アプローチに従うことです。これにより、エントリ時にアプリケーションシェルをキャッシュし、接続に基づいてデータをロードできます。

このアプローチでのキャッシュと提供の最も一般的な方法は、キャッシュからネットワークへのフォールバックを提供することです。この場合、要求されたリソースがキャッシュで利用できない場合は、ネットワーク経由で要求を送信し、応答をキャッシュします。次に、キャッシュから提供します。

これにより、電車の中などの接続が不安定な場合でも、より適切な劣化を行うことができます。

これを実装する例:

const cacheName = "my-cache-v1"

self.addEventListener('fetch', (event) => {
  if (event.request.method === 'GET') {
    event.respondWith(
      caches.match(event.request).then((response) => {
        if (response) {
          return response;
        }
        return fetch(event.request).then((response) => {
          return caches.open(cacheName).then((cache) => {
            cache.put(event.request.url, response.clone());
            return response;
          });
        });
      })
    );
  }
});

上記の例( Service Worker ライフサイクルで必要な手順の1つのみ)では、古いキャッシュエントリも削除する必要があります。

3
LeonH

私が見たほとんどのサービスは、次の方法を使用しています:特定の値までタイムアウトを増やし、サーバーに接続しようとします。最大タイムアウト値に達すると、再接続の次の試行が発生する回数を示す手動の再接続ボタン付きのインジケータが表示されます

2
layonez