ApolloClientを使う時はtypenameとidは必ず含めようという話
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"
}
}
}
}
このオブジェクトには、Person
とPlanet
という二つのオブジェクトが含まれています。Apollo Clientでは、これら全てのオブジェクトに対して固有のcacheIDを生成し、オブジェクトの参照を作成します。
このcacheIDは、デフォルトではオブジェクトのid
と__typename
を組み合わせて生成されます。つまり、___typename:id
の形式でcacheIDが作られます。
上記のオブジェクトの場合、以下のようなcacheIDが生成されます。
Person:cGVvcGxlOjE=
Planet:cGxhbmV0czox
Apollo Clientのキャッシュには、以下のようにPerson
とPlanet
が保存されます。
{
"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 (公式ドキュメント)
- Caching in Apollo (公式ドキュメント) 本記事の"正規化"と"idとtypenameを含めていないとどうなるのか"のセクションはこのドキュメントを参考にしています。
以上が、Apollo Clientのキャッシュと正規化についての理解をまとめたものです。少し複雑な話題かもしれませんが、この記事がApollo Clientを使う際の理解の助けになれば幸いです!
Discussion