背景・目的
ブラウザのキャッシュ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 を用いて確認できる
- ブラウザによる自動キャッシュ削除の可能性がある
実践
下記のようなシナリオで簡単に動作確認をします。
- キャッシュ容量の使用量確認
- 名前付きキャッシュのバージョン管理とデータ保存
- データの取得とキャッシュの活用
- 定期的なキャッシュクリーニング
前提
- VSCode
- Mac OS
事前準備
- プロジェクトフォルダを作成します
git % mkdir frontend-cache-test
- VSCodeでプロジェクトをワークスペースに追加します
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`); } }
-
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; }
-
app.js
を作成し、下記を実装しますimport { checkCacheStorage } from './cache-scripts/storageCheck.js'; const currentCache = 'my-cache-v1'; // キャッシュの管理機能を実行するメイン関数 async function runApp() { // 1. キャッシュの容量確認 await checkCacheStorage(); }
-
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>
-
ローカルサーバを使用して確認します
frontend-cache-test % npx http-server . Starting up http-server, serving .
-
「Run Cache Operations」をクリックします。Consoleに下記が表示されました
2. 名前付きキャッシュのバージョン管理とデータ保存
-
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} にデータが保存されました`); }
-
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;
-
ローカルサーバを再起動します
-
ブラウザに
localhost:8080
を入力し確認します -
「Run Cache Operations」をクリックします。Consoleに下記が表示されました
3.データの取得とキャッシュの活用
-
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; // 保存したデータを返す } }
-
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;
-
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>
-
ローカルサーバを再起動します
-
ブラウザに
localhost:8080
を入力し確認します -
「Run Cache Operations」をクリックします。Consoleに下記が表示されました
-
NW接続を閉じます
-
「Run Cache Operations」をクリックします。Consoleに下記が表示されました
- オフライン用のダミーデータ
考察
今回、キャッシュAPIを用いて、データの保存、容量確認を行う操作を実装しました。ブラウザの開発者ツールを通じて、キャッシュが実際に保存されることを確認しました。
また、オンライン・オフラインでのキャッシュ利用の切り替えも試してみました。
今回の実装では、シンプルなダミーデータのキャッシュの確認のみを行いましたが、今後は以下についても試してみ用途思います。
- キャッシュの有効期限管理:キャッシュに有効期限を設定し、古いデータの自動更新や削除ができるようにする
- リアルタイムデータの管理:実際のAPIからの動的なデータを使い、キャッシュの更新を行う
- 大容量ファイルの管理:画像や動画などの大容量ファイルを効率的にキャッシュし、必要に応じて部分的に削除や更新を行う仕組みを試す
参考