導入
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操作を練習してみることをおすすめします。