CacheStorage

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2018.

安全なコンテキスト用: この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

メモ: この機能はウェブワーカー内で利用可能です。

CacheStorage インターフェイスは、Cache オブジェクトのストレージを表します。

このインターフェイスは、

  • ServiceWorker や他の種類のワーカーまたは window のスコープからアクセスできる、すべての名前付きキャッシュのマスターディレクトリーを提供します(サービスワーカーでの使用には限定されません)。
  • 対応する Cache オブジェクトへの文字列名のマッピングを維持します。

CacheStorage.open() を使用して、Cache インスタンスを取得します。

CacheStorage.match() を使用して、所与の RequestCacheStorage オブジェクトが追跡する Cache オブジェクトのキーであるかどうかを確認します。

CacheStorage には、ウィンドウの Window.caches プロパティまたはワーカーの WorkerGlobalScope.caches を介してアクセスできます。

メモ: CacheStorage は、信頼されていないオリジン(つまり、 HTTPS を使用しないオリジンですが、この定義は将来より複雑になる可能性があります)では常に拒否され、 SecurityError となります。 Firefox でテストする場合は、 Firefox 開発者ツールのオプション/ギアメニューの HTTP による Service Worker を有効化 (ツールボックスを開いたとき) オプションをチェックすることで回避することが可能です。さらに、 CacheStorage はファイルシステムへのアクセスを必要とするため、Firefoxのプライベートモードでは利用できない場合があります。

メモ: CacheStorage.match() は便利なメソッドです。 キャッシュエントリーと一致する同等の機能を実装するには、CacheStorage.keys() からキャッシュ名の配列を返し、CacheStorage.open() で各キャッシュを開き、Cache.match() で必要なものと一致させます。

インスタンスメソッド

CacheStorage.match()

所与の Request が、CacheStorage オブジェクトが追跡する Cache オブジェクトのキーであるかどうかを確認し、その一致で解決する Promise を返します。

CacheStorage.has()

Promise を返します。これは、 cacheName に一致する Cache オブジェクトが存在する場合、true に解決されます。

CacheStorage.open()

Promise を返します。これは、 cacheName に一致する Cache オブジェクトに解決されます(まだ存在しない場合は新しいキャッシュが作成されます)。

CacheStorage.delete()

cacheName に一致する Cache オブジェクトを見つけ、見つかった場合は Cache オブジェクトを削除し、 true に解決される Promise を返します。 Cache オブジェクトが見つからない場合、false に解決されます。

CacheStorage.keys()

Promise を返します。これは、 CacheStorage によって追跡されるすべての名前付き Cache オブジェクトに対応する文字列を含む配列で解決されます。このメソッドを使用して、すべての Cache オブジェクトのリストを反復処理します。

このコードスニペットは、MDN の単純なサービスワーカーの例からのものです(単純なサービスワーカーがライブで実行するのを見る)。 このサービスワーカーのスクリプトは、install イベントが発生するのを待ち、waitUntil を実行してアプリのインストールプロセスを処理します。 これは、CacheStorage.open を呼び出して新しいキャッシュを作成し、Cache.addAll を使用して一連のアセットを追加することで構成されます。

2 番目のコードブロックでは、 FetchEvent が発生するのを待ちます。 次のようなカスタムレスポンスを作成します。

  1. CacheStorage でリクエストに一致するものが見つかったかどうかを確認します。 もしそうなら、それを提供します。
  2. そうでない場合は、ネットワークからリクエストを取得し、最初のブロックで作成されたキャッシュも開き、Cache.put (cache.put(event.request, response.clone())) を使用してリクエストのクローンを追加します。
  3. これが失敗した場合(例えば、ネットワークがダウンしているため)、フォールバックレスポンスを返します。

最後に、FetchEvent.respondWith を使用して、カスタムレスポンスが等しくなったものをすべて返します。

js
self.addEventListener("install", (event) => {
  event.waitUntil(
    caches
      .open("v1")
      .then((cache) =>
        cache.addAll([
          "/",
          "/index.html",
          "/style.css",
          "/app.js",
          "/image-list.js",
          "/star-wars-logo.jpg",
          "/gallery/bountyHunters.jpg",
          "/gallery/myLittleVader.jpg",
          "/gallery/snowTroopers.jpg",
        ]),
      ),
  );
});

self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      // caches.match() は常に解決します
      // ただし、成功の場合はレスポンスに値があります
      if (response !== undefined) {
        return response;
      } else {
        return fetch(event.request)
          .then((response) => {
            // レスポンスは1回のみ使用できます
            // クローンを保存して、1番目のコピーをキャッシュに入れ、
            // 2番目のコピーを提供する必要があります
            let responseClone = response.clone();

            caches.open("v1").then((cache) => {
              cache.put(event.request, responseClone);
            });
            return response;
          })
          .catch(() => caches.match("/gallery/myLittleVader.jpg"));
      }
    }),
  );
});

このスニペットは、サービスワーカーのコンテキストの外部で API を使用する方法を示しており、await 演算子を使用してより読みやすいコードにしています。

js
// キャッシュからデータを取得しようとしますが、フォールバックしてライブで取得します。
async function getData() {
  const cacheVersion = 1;
  const cacheName = `myapp-${cacheVersion}`;
  const url = "https://jsonplaceholder.typicode.com/todos/1";
  let cachedData = await getCachedData(cacheName, url);

  if (cachedData) {
    console.log("取得したキャッシュデータ");
    return cachedData;
  }

  console.log("最新データの取得");

  const cacheStorage = await caches.open(cacheName);
  await cacheStorage.add(url);
  cachedData = await getCachedData(cacheName, url);
  await deleteOldCaches(cacheName);

  return cachedData;
}

// キャッシュからデータを取得します。
async function getCachedData(cacheName, url) {
  const cacheStorage = await caches.open(cacheName);
  const cachedResponse = await cacheStorage.match(url);

  if (!cachedResponse || !cachedResponse.ok) {
    return false;
  }

  return await cachedResponse.json();
}

// 古いキャッシュを削除して、ユーザーのディスク容量を尊重します。
async function deleteOldCaches(currentCache) {
  const keys = await caches.keys();

  for (const key of keys) {
    const isOurCache = key.startsWith("myapp-");
    if (currentCache === key || !isOurCache) {
      continue;
    }
    caches.delete(key);
  }
}

try {
  const data = await getData();
  console.log({ data });
} catch (error) {
  console.error({ error });
}

仕様書

Specification
Service Workers
# cachestorage-interface

ブラウザーの互換性

BCD tables only load in the browser

関連情報