JavaScriptのService Worker入門|オフライン対応とキャッシュ制御

先生

オフラインでもサクサク動くWebサイトを作ろう!Service Workerでキャッシュを制し、ユーザー体験を爆上げ🚀

Service Workerとは?基本概念を理解する

Service Workerは、Webブラウザのバックグラウンドで動作するスクリプトです。Webページとは独立して動作し、プッシュ通知の処理やバックグラウンド同期など、さまざまな機能を提供します。最も重要な機能の一つが、オフラインでのWebサイトの利用を可能にすることです。

Service Workerは、Webページとネットワークの間に立ち、プロキシとして機能します。これにより、ネットワークリクエストをインターセプトし、キャッシュされたコンテンツを提供したり、ネットワークが利用できない場合に代替コンテンツを表示したりできます。

Service WorkerはJavaScriptで記述され、ブラウザのService Worker APIを通じて制御されます。Service Workerは、一度インストールされると、ブラウザが閉じられた後でもバックグラウンドで動作し続けることができます。

Service WorkerはHTTPSでのみ動作します。これは、セキュリティ上の理由からです。また、Service Workerはブラウザのセキュリティモデルに従い、Webページのオリジンポリシーを遵守します。

Service Workerのライフサイクル

Service Workerのライフサイクルは、登録、インストール、アクティベートの3つの主要な段階で構成されます。

登録: WebページからService Workerを登録します。これにより、ブラウザはService Workerスクリプトをダウンロードし、インストールを開始します。

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js')
    .then(function(registration) {
      console.log('Service Worker registered with scope:', registration.scope);
    })
    .catch(function(error) {
      console.log('Service Worker registration failed:', error);
    });
}

インストール: Service Workerがインストールされると、キャッシュの初期設定などを行います。この段階で、古いService Workerからの移行処理も行われます。

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open('my-site-cache')
      .then(function(cache) {
        return cache.addAll([
          '/',
          '/index.html',
          '/style.css',
          '/script.js'
        ]);
      })
  );
});

アクティベート: Service Workerがアクティベートされると、古いService Workerが置き換えられ、新しいService Workerがネットワークリクエストを処理できるようになります。古いキャッシュの削除など、クリーンアップ処理もこの段階で行われます。

self.addEventListener('activate', function(event) {
  var cacheWhitelist = ['my-site-cache'];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

キャッシュ戦略:オフライン対応を強化する

Service Workerのキャッシュ戦略は、Webサイトのオフライン対応を大きく左右します。適切なキャッシュ戦略を選択することで、ネットワークが利用できない場合でも、Webサイトのコンテンツを提供し続けることができます。

Cache first: 最初にキャッシュを確認し、キャッシュにコンテンツが存在する場合は、キャッシュから提供します。キャッシュに存在しない場合は、ネットワークから取得し、キャッシュに保存します。

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }

        // IMPORTANT: Clone the request. A request is a stream
        // and because we've already consumed it once by matching
        // it to the cache, we need to clone it so that the
        // fetch API can consume it as well.
        var fetchRequest = event.request.clone();

        return fetch(fetchRequest).then(
          function(response) {
            // Check if we received a valid response
            if(!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }

            // IMPORTANT: Clone the response. A response is a stream
            // and because we need the browser to consume the response
            // as well as the cache consuming the response, we need
            // to clone it so we have two streams.
            var responseToCache = response.clone();

            caches.open('my-site-cache')
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });

            return response;
          }
        );
      })
    );
});

Network first: 最初にネットワークからコンテンツを取得し、取得に成功した場合は、キャッシュに保存して提供します。ネットワークが利用できない場合は、キャッシュから提供します。この戦略は、常に最新のコンテンツを提供したい場合に適しています。

Cache only: 常にキャッシュからコンテンツを提供します。ネットワークは使用しません。静的なアセットに適しています。

Network only: 常にネットワークからコンテンツを取得します。キャッシュは使用しません。常に最新のコンテンツを取得する必要がある場合に適しています。

Stale-while-revalidate: キャッシュからコンテンツをすぐに提供し、バックグラウンドでネットワークから最新のコンテンツを取得してキャッシュを更新します。これにより、常に最新のコンテンツを提供しつつ、高速な応答を実現できます。

Service Workerのデバッグ方法

Service Workerのデバッグは、通常のJavaScriptコードのデバッグとは少し異なります。Chrome DevToolsなどの開発者ツールを使用すると、Service Workerの登録状況、キャッシュの状態、ネットワークリクエストなどを確認できます。

Chrome DevToolsの「Application」タブにある「Service Workers」セクションでは、登録されているService Workerの状態を確認できます。また、「Cache Storage」セクションでは、キャッシュに保存されているコンテンツを確認できます。

Service Workerのコンソールログは、通常のWebページのコンソールログとは別に表示されます。Service Workerのコード内でconsole.log()を使用すると、Service Workerのコンソールにログが出力されます。

Service Workerのデバッグ時には、キャッシュをクリアしたり、Service Workerの登録を解除したりする必要がある場合があります。Chrome DevToolsを使用すると、これらの操作を簡単に行うことができます。

参考リンク

まとめ

Service Workerは、Webサイトのオフライン対応やパフォーマンス向上に役立つ強力なツールです。Service Workerの基本概念、ライフサイクル、キャッシュ戦略を理解し、適切に活用することで、ユーザーエクスペリエンスを大幅に改善することができます。ぜひService Workerを導入して、より優れたWebサイトを開発してください。