TL;DR
このページでは、JavaScript IndexedDB の魅力とその使い方を解説しますね。一言で言うと、IndexedDB は JavaScript で使える強力なデータベースです。
開発環境 | バージョン |
---|---|
Next.js | 13.4.4 |
TypeScript | 5.0.4 |
Emotion | 11.11.0 |
React | 18.2.0 |
IndexedDB とは?
皆さんはデータをどこに保存しますか?ローカルの変数?それともサーバー?どちらも有効な方法ですが、ブラウザ内にも強力なデータストレージが存在します。それが IndexedDB です。IndexedDB は JavaScript で利用できる Web 標準のデータベースで、オフラインでも安心して使えます。
IndexedDB の利用法は非常にシンプルです。まずデータベースを開きます。
const openRequest = indexedDB.open('myDatabase', 1)
このようにindexedDB.open
メソッドを呼び出すだけで、新しいデータベースが開かれます。この際、第一引数にはデータベースの名前を、第二引数にはデータベースのバージョンを指定します。
第二引数
IndexedDB の open
メソッドの第二引数で指定するのはデータベースのバージョン番号です。このバージョン番号は、整数で指定します。
let openRequest = indexedDB.open('myDatabase', 1)
上記のコードでは、データベース "myDatabase" のバージョン 1 を開くように指定しています。
バージョンはデータベースのスキーマ(構造)を管理するために使用されます。たとえば、新しいオブジェクトストアを作成したり、既存のオブジェクトストアにインデックスを追加したりする場合、データベースのバージョンを上げる必要があります。
新しいバージョンのデータベースを開くと、onupgradeneeded
イベントが発火します。このイベント内では、データベースのスキーマを変更することができます。つまり、新しいオブジェクトストアを作成したり、インデックスを追加したりすることができます。
また、データベースのバージョンは一度設定すると下げることはできません。これは、データの整合性を保つための重要な機能です。
以下に、新しいバージョンのデータベースを開いて新しいオブジェクトストアを作成する例を示します。
let openRequest = indexedDB.open('myDatabase', 2) // バージョンを2に上げる
openRequest.onupgradeneeded = function () {
let db = openRequest.result
if (!db.objectStoreNames.contains('magazines')) {
// "magazines"という名前のオブジェクトストアが存在しなければ作成
db.createObjectStore('magazines', { keyPath: 'id' }) // キーとなるパスを指定
}
}
ここでは、バージョンを 2 に上げて "magazines" という新しいオブジェクトストアを作成しています。
このように、バージョン管理を理解し利用することで、データベースのスキーマを効果的に管理することができます。
データの保持期間、消失条件
IndexedDB のデータベースは、ブラウザが管理します。ユーザーが明示的にブラウザのストレージをクリアしない限り、データは消えません。また、IndexedDB は Web ページがリロードされてもデータが保持されるため、セッション間でデータを保存するのに適しています。
ただし、以下のような状況でデータが消失する可能性があります。
- ユーザーが自身のブラウザの設定でデータをクリアする。
- ブラウザがディスクスペースを確保するためにデータを削除する。これは特にデバイスの空き容量が少ない場合に発生します。この挙動はブラウザによるものなので、どのデータが削除されるかは確定的ではありません。
- 一部のプライバシーフォーカスのブラウザは、閲覧履歴をクリアするための設定がある。これを使うと IndexedDB のデータも消える可能性があります。
したがって、IndexedDB は永続的なストレージとして使用できますが、データが消失しないという保証はありません。重要なデータはサーバー側にもバックアップを取るなど、適切なデータ管理を行うことが重要です。
データの作成と読み出し
それでは、実際にデータを IndexedDB に保存してみましょう。そのためには、まずオブジェクトストアという概念を理解する必要があります。オブジェクトストアはデータベース内の「棚」のようなもので、データの保存場所を定義します。
type DBEvent = Event & {
target: IDBOpenDBRequest
}
const openRequest = indexedDB.open('myDatabase', 1)
openRequest.onupgradeneeded = (event: DBEvent) => {
const db = event.target.result
db.createObjectStore('myObjectStore')
}
このコードは新しいデータベースを開き、新しいオブジェクトストアを作成します。onupgradeneeded
イベントはデータベースが開かれた時、またはバージョンが上がった時に呼び出されます。ここでオブジェクトストアを作成することができます。
そしてデータを保存するには、オブジェクトストアのadd
メソッドを使用します。
const openRequest = indexedDB.open('myDatabase', 1)
openRequest.onsuccess = (event: DBEvent) => {
const db = event.target.result
const transaction = db.transaction('myObjectStore', 'readwrite')
const objectStore = transaction.objectStore('myObjectStore')
objectStore.add({ hello: 'world' })
}
以上でデータの保存ができます。onsuccess
イベントはデータベースが正常に開かれた時に発火します。そこでトランザクションを作成し、その中にオブジェクトストアを開きます。最後にadd
メソッドでデータを追加します。
データの更新と削除
データの更新や削除も同様に簡単に行うことができます。更新にはput
メソッドを、削除にはdelete
メソッドを使用します。
const openRequest = indexedDB.open('myDatabase', 1)
openRequest.onsuccess = (event: DBEvent) => {
const db = event.target.result
const transaction = db.transaction('myObjectStore', 'readwrite')
const objectStore = transaction.objectStore('myObjectStore')
// Update
objectStore.put({ hello: 'new world' }, 'myKey')
// Delete
objectStore.delete('myKey')
}
このように IndexedDB を使うと、データの操作が非常に簡単になります。しかもこれらのデータはブラウザ内に保存されるため、サーバーとの通信がなくてもデータの操作が可能です。
オブジェクトストア
IndexedDB の中に存在する重要な考え方の一つが、オブジェクトストアです。IndexedDB は、JavaScript でブラウザ内のデータベースを操作するための API ですが、その中でデータを保存するための場所としてオブジェクトストアが存在します。
オブジェクトストアは、名前の通り、JavaScript のオブジェクトを保存する場所であり、それぞれのオブジェクトストアにはユニークな名前がつけられています。一つの IndexedDB データベース内には複数のオブジェクトストアを作成することができます。これは、リレーショナルデータベースのテーブルに似ていると考えると理解が深まるかもしれません。
また、オブジェクトストア内の各オブジェクトはキーによって一意に識別されます。このキーは、オブジェクトのプロパティの一つである場合もありますし、オブジェクトとは独立にデータベースが生成する場合もあります。
以下に、オブジェクトストアを作成し、データを保存する基本的なコードを示します。
// データベースを開く
let openRequest = indexedDB.open('myDatabase', 1)
openRequest.onupgradeneeded = function () {
// データベースのバージョンが上がったとき、オブジェクトストアを作成
let db = openRequest.result
if (!db.objectStoreNames.contains('books')) {
// "books"という名前のオブジェクトストアが存在しなければ作成
db.createObjectStore('books', { keyPath: 'isbn' }) // キーとなるパスを指定
}
}
openRequest.onsuccess = function () {
let db = openRequest.result
let transaction = db.transaction('books', 'readwrite') // "books"というオブジェクトストアに対してトランザクションを開始
let books = transaction.objectStore('books') // オブジェクトストアを取得
// データを追加
let request = books.add({
isbn: '123456',
title: 'JavaScript入門',
author: '田中 太郎',
})
request.onsuccess = function () {
console.log('書籍が追加されました')
}
}
ここでは、まず indexedDB.open
を用いてデータベースを開いています。その後、onupgradeneeded
イベント内で、"books"という名前のオブジェクトストアを作成しています。createObjectStore
の第二引数にはオプションを指定し、ここでは keyPath
を指定しています。この keyPath
は、オブジェクト内の何をキーとするかを指定するオプションで、ここでは "isbn" をキーとしています。
そして、onsuccess
イベント内で、オブジェクトストアに対するトランザクションを開始し、オブジェクトストアを取得しています。そして、add
メソッドを使ってデータを追加しています。
このように、オブジェクトストアを理解し使いこなすことで、JavaScript でブラウザ内のデータベースを柔軟に操作することができます。