IndexedDB の使用に関するベスト プラクティス

IndexedDB と一般的な状態管理ライブラリの間でアプリケーションの状態を同期するためのベスト プラクティスを学びます。

ユーザーが最初にウェブサイトまたはアプリケーションを読み込むと、多くの場合、この作業には相当量の作業が UI のレンダリングに使用される初期アプリの状態を構築します。たとえば アプリはクライアントサイドでユーザーを認証し、API リクエストを複数発行してからでないと、 ページに表示するデータを指定します

アプリケーションの状態を IndexedDB を使用すると、アプリの速度を落とさずに 再訪問の読み込み時間これにより、アプリはバックグラウンドで API サービスと同期できるようになります。 新しいデータで UI の更新を遅らせたり、 stale-while-revalidate 戦略を実施する場合があります。

IndexedDB のもう一つの用途として、ユーザーが作成したコンテンツを一時的なストアとして保存することもできます。 リモートデータのクライアントサイド キャッシュとしてアップロードできます。もちろんその両方も可能です。

しかし、IndexedDB を使用する際には考慮すべき重要な点が数多くありますが、 API を初めて使用するデベロッパーにとっては明白です。この記事では、よくある質問とその回答をご紹介します。 IndexedDB でデータを永続化する際に留意すべき重要事項の一部を紹介します。

アプリの予測可能性を維持する

IndexedDB が複雑になるのは、その原因となっている要因があまりにも多いことに起因します。 (開発者)は制御できません。このセクションでは、留意すべき問題の多くについて説明します。 使用することをおすすめします

プラットフォームによっては IndexedDB に保存できないデータがある

画像や動画など、ユーザー生成の大きなファイルを保存する場合は、 File オブジェクトまたは Blob オブジェクトとして指定します。これは、一部のプラットフォームでは機能しますが、他のプラットフォームでは失敗します。Safari: オン 特に iOS では、IndexedDB に Blob を保存できません。

幸いなことに、BlobArrayBuffer に変換することはそれほど難しくなく、その逆も同様です。保存 IndexedDB の ArrayBuffer は十分にサポートされています。

ただし、Blob には MIME タイプがありますが、ArrayBuffer には MIME タイプがないことに注意してください。次の操作が必要です。 型をバッファと一緒に格納して正しく変換する必要があります。

ArrayBufferBlob に変換するには、単に Blob コンストラクタを使用します。

function arrayBufferToBlob(buffer, type) {
  return new Blob([buffer], { type: type });
}

もう一方はやや複雑で、非同期プロセスです。こちらの FileReader オブジェクトを使用して blob を ArrayBuffer として読み取ります。読み取りが完了すると、loadend イベントがトリガーされます。このプロセスは、次のように Promise でラップできます。

function blobToArrayBuffer(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.addEventListener('loadend', () => {
      resolve(reader.result);
    });
    reader.addEventListener('error', reject);
    reader.readAsArrayBuffer(blob);
  });
}

ストレージへの書き込みが失敗する可能性があります

IndexedDB への書き込み時のエラーはさまざまな原因で発生する可能性があり、 デベロッパーが管理することはできません。たとえば、現在のところ、一部のブラウザでは シークレット ブラウジング モードにおける IndexedDB への書き込み また、ユーザーが使用しているデバイスのディスク容量が残りわずかになっている可能性もあります。 ブラウザでは、何も保存できなくなります。

そのため、インフラストラクチャには常に適切なエラー処理を実装し、 IndexedDB コード。つまり、アプリケーションの状態をメモリ( シークレット ブラウジング モードで実行しているときや、シークレット ブラウジング モードで実行しているときや、 使用できない場合(ストレージを必要とする他のアプリ機能の一部が あります。

IndexedDB オペレーションのエラーをキャッチするには、error イベントのイベント ハンドラを追加します。 IDBDatabaseIDBTransaction、または IDBRequest のオブジェクトを作成する際に使用するコードです。

const request = db.open('example-db', 1);
request.addEventListener('error', (event) => {
  console.log('Request error:', request.error);
};

保存されたデータがユーザーによって変更または削除された可能性があります

不正アクセスを制限できるサーバーサイドのデータベースと異なり、クライアントサイドのデータベースは ブラウザ拡張機能とデベロッパー ツールからアクセスでき、ユーザーが削除できます。

ユーザーがローカルに保存されたデータを変更することはめったにありませんが、 消去します。アプリケーションがエラーなくこの両方を処理できることが重要です。

保存されたデータは最新でない可能性があります

前のセクションと同様に、ユーザー自身がデータを変更していなくても、 ストレージにあるデータが古いバージョンのコードによって書き込まれた可能性があります。 バグのあるバージョンです

IndexedDB には、スキーマ バージョンとアップグレードのサポートが組み込まれています。 IDBOpenDBRequest.onupgradeneeded() method;ただし、アップグレード コードは、ユーザーが処理できるように記述する必要があります。 (バグのあるバージョンを含む)。

考えられるすべての項目を手動でテストすることは不可能な場合が多いため、ここでは単体テストが非常に有用である アップグレード パスとケースを確認できます。

アプリのパフォーマンスを維持する

IndexedDB の主な機能の一つは非同期 API ですが、 パフォーマンスを気にしなくてよいということですさまざまなケースで 不適切に使用するとメインスレッドがブロックされ、ジャンクが発生したり応答しなくなったりする可能性があります。

原則として、IndexedDB の読み取りと書き込みは、データに必要なサイズを超えてはならない あります。

IndexedDB では、ネストされた大きなオブジェクトを 1 つのレコードとして格納できますが、 デベロッパーにとって非常に便利であるにもかかわらず、そのような手法は避けるべきです。「 その理由は、IndexedDB がオブジェクトを格納するときに、まずそのオブジェクトの 構造化クローン 構造化クローン作成プロセスはメインスレッドで行われます。値が大きくなるほど ブロック時間が長くなります。

このため、IndexedDB にアプリケーションの状態を保持させる方法を計画する場合、いくつかの課題が生じます。 一般的な状態管理ライブラリ(Redux など)を使用するには、 状態ツリー全体を単一の JavaScript オブジェクトとして扱います。

この方法で状態を管理すると、多くの利点があります(たとえば、 状態ツリー全体を 1 つのレコードとして IndexedDB に保存する場合もありますが、 変更のたびにこれを行うと(スロットルまたはデバウンスが行われた場合でも)、 メインスレッドを不必要にブロックすると、書き込みエラーが発生する可能性が高まります。 場合によっては、ブラウザタブがクラッシュしたり、応答しなくなったりすることもあります。

状態ツリー全体を 1 つのレコードに格納するのではなく、状態ツリーを個々のレコードに 実際に変更されたレコードのみを更新します

画像、音楽、動画などの大きなアイテムを IndexedDB に保存している場合も同様です。各アイテムを保存する 固有のキーを使用して構造化データを取得できます。 バイナリファイルの取得コストを 支払う必要はありません

ほとんどのベスト プラクティスと同様、これはオールオアナッシングのルールではありません。複数のエンドポイントを 状態オブジェクトを分割して最小限の変更セットを書き込み、データをサブツリーに分割します。 常に状態ツリー全体を書き込むよりも、これらを記述する方が望ましいです。リトル 改善されるということは、まったく改善しないよりよいでしょう。

最後に、常にパフォーマンスへの影響を測定する必要があります。 時間のかかる作業ですただし、IndexedDB への書き込みは小規模なもののほうが大規模なものよりもパフォーマンスが優れているのは事実です アプリケーションが実行している IndexedDB への書き込みが実際に 長いタスク メインスレッドをブロックし、ユーザー エクスペリエンスを低下させます。測定は重要です 把握するのに役立ちます

まとめ

デベロッパーは IndexedDB などのクライアント ストレージ メカニズムを活用して、 セッション間で状態を維持するだけでなく、 再訪問時に初期状態を読み込む必要があります。

IndexedDB を適切に使用することで、ユーザー エクスペリエンスは大幅に向上しますが、誤って使用することや、 エラーケースに対応できないと、アプリが壊れたりユーザーが不満を覚えたりする可能性があります。

クライアント ストレージには制御できない多くの要因が関係するため、コードを適切に運用することが重要 初めのうちは発生する可能性が低いと思われる場合でも、エラーを適切に処理します。