🌌

ApolloClientを使う時はtypenameとidは必ず含めようという話

2023/07/17に公開

Apollo Clientのキャッシュと正規化についての公式ドキュメントを読んで、深く理解することができたので、ここにその内容を備忘録としてまとめます。

この記事の対象者

  • Apollo Clientを使っている人、または使う予定がある人
  • キャッシュの仕組みについてよく理解していない人

Apollo Clientとは?

Apollo ClientはGraphQLデータを効率的に管理するための強力でフレキシブルなJavaScriptライブラリです。

Apollo Clientのキャッシュの仕組み

概要

Apollo ClientのInMemoryCacheは、フラットなキーバリューストアとしてデータを保存しています。つまり、階層的なデータ構造を持たないので、キーによる直接の参照を可能にし、検索効率を高めています。

しかし、GraphQLのレスポンスは通常、ネストされたオブジェクトで返されます。では、どのようにしてフラットなキー-値ストアでネストされたオブジェクトを表現するのでしょうか?

正規化

ここで登場するのが、正規化というプロセスです。正規化とは、ネストされたオブジェクトをフラットな形に変換することです。具体的な例を見てみましょう。

以下のJSONオブジェクトがあるとします。

{
  "data": {
    "person": {
      "__typename": "Person",
      "id": "cGVvcGxlOjE=",
      "name": "Luke Skywalker",
      "homeworld": {
        "__typename": "Planet",
        "id": "cGxhbmV0czox",
        "name": "Tatooine"
      }
    }
  }
}

このオブジェクトには、PersonPlanetという二つのオブジェクトが含まれています。Apollo Clientでは、これら全てのオブジェクトに対して固有のcacheIDを生成し、オブジェクトの参照を作成します。

このcacheIDは、デフォルトではオブジェクトのid__typenameを組み合わせて生成されます。つまり、___typename:idの形式でcacheIDが作られます。

上記のオブジェクトの場合、以下のようなcacheIDが生成されます。

  • Person:cGVvcGxlOjE=
  • Planet:cGxhbmV0czox

Apollo Clientのキャッシュには、以下のようにPersonPlanetが保存されます。

{
  "Person:cGVvcGxlOjE=": {
    "__typename": "Person",
    "id": "cGVvcGxlOjE=",
    "name": "Luke Skywalker",
    "homeworld": {
      "__ref": "Planet:cGxhbmV0czox"
    }
  },
  "Planet:cGxhbmV0czox": {
    "__typename": "Planet",
    "id": "cGxhbmV0czox",
    "name": "Tatooine"
  }
}

cacheIDが生成されたら、オブジェクトを含むフィールド(この場合、homeworld)の参照をcacheIDに置き換えます。

{
  "data": {
    "person": {
      "__typename": "Person",
      "id": "cGVvcGxlOjE=",
      "name": "Luke Skywalker",
      "homeworld": {
+	"__ref": "Planet:cGxhbmV0czox"
-	"__typename": "Planet",
-	"id": "cGxhbmV0czox",
-	"name": "Tatooine"
      }
    }
  }
}

idとtypenameを含めていないとどうなるのか

もしオブジェクトがid__typenameを含んでいない場合、Apollo ClientはcacheIDを生成することができません。その結果、Apollo Clientはそのオブジェクトを親オブジェクトを通じてのみ参照できます。言い換えると、完全なクエリパスを通じてのみ参照できるようになります。

これはパフォーマンスの低下を招きます。

参考リンク

以上が、Apollo Clientのキャッシュと正規化についての理解をまとめたものです。少し複雑な話題かもしれませんが、この記事がApollo Clientを使う際の理解の助けになれば幸いです!

Discussion