2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ブラウザのキャッシュAPIを試してみた

Posted at

背景・目的

ブラウザのキャッシュAPIについて調べる機会があったので、簡単に整理し試してみます。

まとめ

下記に特徴をまとめます

特徴 説明
Cacheインターフェイス ・Request/Responseオブジェクトのペアを保存するストレージの仕組みを提供する
・Cache オブジェクトがどのくらい持続するかはブラウザーに依存する
・サービスワーカーだけでなく、ブラウザのウィンドウスコープ(通常のウェブページ)」でも使える
キャッシュの管理 ・ひとつのオリジンが、複数の名前付き Cache オブジェクトを保有することができる
・複数の名前付きキャッシュを持てる
・キャッシュ更新の管理は開発者の責任
・CacheStorage.open() で特定の名前のキャッシュを開く

概要

下記を基に整理します

Cache

Cache インターフェイスは、 Request / Response オブジェクトのペアを保存するストレージの仕組みを提供します。Cache オブジェクトがどのくらい持続するかはブラウザーに依存しますが、単一のオリジンのスクリプトは通常、以前に生成された Cache オブジェクトの存在を頼りにすることができます。Cache インターフェイスは、ワーカーと同様にウィンドウスコープにも公開されていることに注意してください。サービスワーカーの仕様で定義されているとはいえ、サービスワーカーと共に使用する必要はありません。

  • Cacheインターフェイスは、Request/Responseオブジェクトのペアを保存するストレージの仕組みを提供
  • Cache オブジェクトがどのくらい持続するかはブラウザーに依存する
  • サービスワーカーだけでなく、ブラウザのウィンドウスコープ(通常のウェブページ)」でも使える

ひとつのオリジンが、複数の名前付き Cache オブジェクトを保有することができます。スクリプト(例えば ServiceWorker) が Cache の更新をどのように処理するかを実装するのは作者の責任です。Cache 内のアイテムは、明示的に要求されない限り更新されませんし、削除されない限り有効期限はありません。 CacheStorage.open() を使用して特定の名前付き Cache オブジェクトを開き、それから任意の Cache のメソッドを呼び出して Cache を管理します。

  • ひとつのオリジンが、複数の名前付き Cache オブジェクトを保有することができる
  • 複数の名前付きキャッシュを持てる
  • キャッシュ更新の管理は開発者の責任
  • CacheStorage.open() で特定の名前のキャッシュを開く

また、定期的にキャッシュ項目を掃除する必要があります。各ブラウザーは、あるオリジンで使用できるキャッシュストレージの総量に厳しい制限を設けています。 Cache 容量の概算の使用量は StorageManager.estimate() API を用いて確認することができます。ブラウザーはディスク容量の管理に最善を尽くしますが、あるオリジンのキャッシュストレージを削除することがあります。ブラウザーはふつう、あるオリジンのデータをすべて削除するか、まったく削除しないかのいずれかです。名前を用いてキャッシュをバージョン管理し、安全に操作できるスクリプトのバージョンからのみキャッシュを使用するようにしてください。詳細は、古いキャッシュの削除を確認してください。

  • 各ブラウザーは、あるオリジンで使用できるキャッシュストレージの総量に厳しい制限を設けている
    • Cache 容量の概算の使用量は StorageManager.estimate() API を用いて確認できる
  • ブラウザによる自動キャッシュ削除の可能性がある

実践

下記のようなシナリオで簡単に動作確認をします。

  1. キャッシュ容量の使用量確認
  2. 名前付きキャッシュのバージョン管理とデータ保存
  3. データの取得とキャッシュの活用
  4. 定期的なキャッシュクリーニング

前提

  • VSCode
  • Mac OS

事前準備

  1. プロジェクトフォルダを作成します
    git % mkdir frontend-cache-test
    
  2. VSCodeでプロジェクトをワークスペースに追加します

1. キャッシュ容量の使用量確認

  1. cache-scripts/storageCheck.jsを作成し、下記を実装します

    // storageCheck.js
    export async function checkCacheStorage() {
      if ('storage' in navigator && 'estimate' in navigator.storage) {
          // StorageManager.estimate()を使用して、キャッシュ容量の使用料と総容量を確認します
          const estimate = await navigator.storage.estimate();
          console.log(`使用容量: ${(estimate.usage / 1024 / 1024).toFixed(2)} MB`);
          console.log(`総容量: ${(estimate.quota / 1024 / 1024).toFixed(2)} MB`);
      }
    }
    
  2. assets/styles.cssを作成し、下記を実装します

    /* assets/styles.css */
    
    body {
        font-family: Arial, sans-serif;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100vh;
        margin: 0;
        background-color: #f4f4f9;
    }
    
    h1 {
        color: #333;
        font-size: 24px;
        margin-bottom: 20px;
    }
    
    button {
        padding: 10px 20px;
        font-size: 16px;
        color: #fff;
        background-color: #007bff;
        border: none;
        border-radius: 5px;
        cursor: pointer;
    }
    
    button:hover {
        background-color: #0056b3;
    }
    
    button:focus {
        outline: none;
    }
    
  3. app.jsを作成し、下記を実装します

    import { checkCacheStorage } from './cache-scripts/storageCheck.js';
    
    const currentCache = 'my-cache-v1';
    
    // キャッシュの管理機能を実行するメイン関数
    async function runApp() {
        // 1. キャッシュの容量確認
        await checkCacheStorage();
    
    }
    
  4. index.htmlを作成し、下記を実装します

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Cache API Demo</title>
        <link rel="stylesheet" href="assets/styles.css">
    </head>
    <body>
        <h1>Cache API Demo</h1>
        <button onclick="runApp()">Run Cache Operations</button>
        <script type="module" src="app.js"></script>
    </body>
    </html>
    
  5. ローカルサーバを使用して確認します

    frontend-cache-test % npx http-server .
    Starting up http-server, serving .
    
  6. ブラウザにlocalhost:8080を入力し確認します。表示されました
    image.png

  7. 「Run Cache Operations」をクリックします。Consoleに下記が表示されました

    • 使用容量: 0.00 MB
    • 総容量: 1083.16 MB
      image.png

2. 名前付きキャッシュのバージョン管理とデータ保存

  1. cache-scripts/cacheManager.jsを作成し、下記を実装します

    // cacheManager.js
    export async function saveToCache(data, cacheName) {
        const cache = await caches.open(cacheName);
        await cache.put('/demo-data', new Response(JSON.stringify(data)));
        console.log(`${cacheName} にデータが保存されました`);
    }
    
  2. app.jsを修正します(2を追加します)

    // app.js
    import { checkCacheStorage } from './cache-scripts/storageCheck.js';
    
    // 2で追加
    import { saveToCache } from './cache-scripts/cacheManager.js';
    
    
    const currentCache = 'my-cache-v1';
    
    // キャッシュの管理機能を実行するメイン関数
    async function runApp() {
        // 1. キャッシュの容量確認
        await checkCacheStorage();
    
    
        // 2. 名前付きキャッシュへのデータ保存
        // ダミーデータとして大きな配列を作成
        const dummyData = {
          content: 'オフライン用のダミーデータ',
          largeData: Array(10000).fill('データサンプル')
        };
        await saveToCache(dummyData, currentCache);
    
    }
    
    // グローバルスコープにrunAppを登録
    window.runApp = runApp;
    
    
  3. ローカルサーバを再起動します

  4. ブラウザにlocalhost:8080を入力し確認します

  5. 「Run Cache Operations」をクリックします。Consoleに下記が表示されました

    • 「my-cache-v1 にデータが保存されました」
      image.png
  6. もう一度クリックすると使用容量が増えました
    image.png

3.データの取得とキャッシュの活用

  1. cache-scripts/fetchData.jsを作成し、下記を実装します

    • オフライン時には、キャッシュAPIを利用してキャッシュからデータを取得します
    • オンライン時には、APIからデータを取得し、saveToCache関数を使用してキャッシュにも保存します
    // fetchData.js
    import { saveToCache } from './cacheManager.js';
    
    // キャッシュまたはネットワークからデータを取得する関数
    export async function fetchData(cacheName) {
        const cache = await caches.open(cacheName);
    
        if (!navigator.onLine) {
            // オフライン時にはキャッシュからデータを取得
            const cachedResponse = await cache.match('/demo-data');
            if (cachedResponse) {
                return await cachedResponse.json(); // キャッシュからデータを取得
            } else {
                return { content: 'オフラインですがキャッシュデータがありません' }; // キャッシュが空の場合
            }
        } else {
            // オンライン時にはダミーデータを保存してから取得
            const data = { content: 'オンラインからのデータ', largeData: Array(10000).fill('データサンプル') };
            await saveToCache(data, cacheName); // ダミーデータをキャッシュに保存
            return data; // 保存したデータを返す
        }
    }
    
    
  2. app.jsにfetchDataをインポートします

    // app.js
    import { checkCacheStorage } from './cache-scripts/storageCheck.js';
    
    // 2で追加
    import { saveToCache } from './cache-scripts/cacheManager.js';
    
    // 3で追加
    import { fetchData } from './cache-scripts/fetchData.js';
    
    
    
    const currentCache = 'my-cache-v1';
    
    // キャッシュの管理機能を実行するメイン関数
    async function runApp() {
        // 1. キャッシュの容量確認
        await checkCacheStorage();
    
        // 2. 名前付きキャッシュへのデータ保存
        const data = { content: 'バージョン1のデータ' };
        await saveToCache(data, currentCache);
    
        // 3. データの取得とキャッシュの活用
        const fetchedData = await fetchData(currentCache);
        document.getElementById('output').innerText = fetchedData.content;
    
    
    }
    
    // グローバルスコープにrunAppを登録
    window.runApp = runApp;
    
  3. index.htmlに表示用の要素を追加します

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Cache API Demo</title>
        <link rel="stylesheet" href="assets/styles.css">
    </head>
    <body>
        <h1>Cache API Demo</h1>
        <button onclick="runApp()">Run Cache Operations</button>
    
        <!-- 取得したデータを表示する要素 -->
        <div id="output"></div>
    
    
        <script type="module" src="app.js"></script>
    </body>
    </html>
    
  4. ローカルサーバを再起動します

  5. ブラウザにlocalhost:8080を入力し確認します

  6. 「Run Cache Operations」をクリックします。Consoleに下記が表示されました

    • オンラインからのデータ
      image.png
  7. NW接続を閉じます

  8. 「Run Cache Operations」をクリックします。Consoleに下記が表示されました

    • オフライン用のダミーデータ

    image.png

考察

今回、キャッシュAPIを用いて、データの保存、容量確認を行う操作を実装しました。ブラウザの開発者ツールを通じて、キャッシュが実際に保存されることを確認しました。
また、オンライン・オフラインでのキャッシュ利用の切り替えも試してみました。

今回の実装では、シンプルなダミーデータのキャッシュの確認のみを行いましたが、今後は以下についても試してみ用途思います。

  • キャッシュの有効期限管理:キャッシュに有効期限を設定し、古いデータの自動更新や削除ができるようにする
  • リアルタイムデータの管理:実際のAPIからの動的なデータを使い、キャッシュの更新を行う
  • 大容量ファイルの管理:画像や動画などの大容量ファイルを効率的にキャッシュし、必要に応じて部分的に削除や更新を行う仕組みを試す

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?