【JS応用|豆知識】フロントエンドで大容量データを扱う!IndexedDBの活用術

導入

Webアプリケーションでブラウザにデータを保存したいとき、皆さんは何を思い浮かべますか?localStorageは手軽ですが、容量制限(通常5MB程度)があり、同期処理のためメインスレッドをブロックする欠点があります。今回解説する「IndexedDB」は、ブラウザ内に構築できる非同期型のNoSQLデータベースです。オフライン対応のアプリ開発や、大量のJSONデータを扱う際に、ユーザーの体感を損なわずにデータを永続化できる非常に重要な技術です。

基礎知識

IndexedDBは、キー・バリュー形式でデータを保存するトランザクションベースのデータベースです。主な特徴は以下の3点です。
1. 非同期処理:Promiseやイベントベースで動作し、UIのフリーズを防ぎます。
2. 大容量:ディスク容量に依存しますが、数GB単位の保存も可能です。
3. 構造化データの保存:JavaScriptのオブジェクトをそのまま保存できるため、変換の手間が省けます。
概念として「データベース」「オブジェクトストア(テーブルのようなもの)」「トランザクション(一連の処理の単位)」を理解しておくことが重要です。

実装/解決策

IndexedDBのAPIは標準だと記述が冗長になりがちです。実務では「idb」のような軽量なラッパーライブラリを使うのが一般的ですが、まずは生のAPIで基本の「接続→ストア作成→データ追加」の流れを押さえましょう。

サンプルプログラム

以下のコードは、ブラウザのコンソールに貼り付けて動作を確認できます。

// データベース名とバージョンを定義
const dbName = "MyDatabase";
const request = indexedDB.open(dbName, 1);

// データベースの初回作成時、またはバージョンアップ時に実行される
request.onupgradeneeded = (event) => {
  const db = event.target.result;
  // 'users'という名前のオブジェクトストアを作成(キーはid)
  if (!db.objectStoreNames.contains("users")) {
    db.createObjectStore("users", { keyPath: "id" });
  }
};

// 接続成功時の処理
request.onsuccess = (event) => {
  const db = event.target.result;
  
  // トランザクションを開始し、データを追加する
  const transaction = db.transaction(["users"], "readwrite");
  const store = transaction.objectStore("users");
  
  const userData = { id: 1, name: "フロントエンドエンジニア", role: "admin" };
  const addRequest = store.add(userData);
  
  addRequest.onsuccess = () => console.log("データが保存されました!");
  addRequest.onerror = () => console.error("保存失敗");
};

応用・注意点

IndexedDBを利用する際に陥りやすい罠として、「非同期処理の管理」があります。複数の処理を連続で行う際は、Promiseでラップしてasync/awaitで記述できるように設計すると、コードの可読性が格段に向上します。
また、ブラウザのプライベートモードやクリーンアップ機能によってデータが削除される可能性がある点にも注意が必要です。あくまでキャッシュやローカルデータの補助として利用し、重要なデータは必ずサーバーサイドと同期させる設計を心がけましょう。まずは簡単なToDoリストアプリなどで、データのCRUD操作を練習してみることをおすすめします。

タイトルとURLをコピーしました