概要
GraphQLとは別のクエリー言語型の API である Falcor 1について調べました。
Falcor とは
Netflix が開発したサーバーとクライアント間のデータのやりとりの仕様です。
Facebook の GraphQL / relay と同じように、RESTful な API の問題を解決するために開発されました。
REST の問題点は Facebook の GraphQL のページにまとめられています。(参考)
Falcor でも次のような問題が解決できます。
- 複雑なデータを取ろうとすると API を何度も呼ばないといけない。
- 例:一覧を取得後に、各要素の詳細を1つずつ取得する、など
- 不要なデータフィールドも取得してしまう。
- 例:name だけ欲しいのに avatar_url とかもついてくる。
準備
Falcor のサンプルの falcor-express-demo を使って動きを見ながら Falcor の仕様を理解したいと思います。
サンプルを npm install && npm start
し、http://localhost:9090 アクセスすると真っ白な画面が表示されます。
※ mac では node.js v4 ではnpm i
でエラーになったので、node.js v0.12 で確認しています。
GraphQLのスキーマのように API の形が簡単にわかる方法がないようですので、サーバーのソースコード を参考にしながらいろいろ試してみます。
Path
REST では URI によってリソースを指定しますが、falcor では Path によって指定します。
Path は名前の通り、データの階層をパスを使って指定しますが、簡単なクエリーも指定できます。
サンプルコードでは genrelist
というジャンルのリストを取得するパスが用意されています。
まず、ジャンルリストの1つ目を取得してみます。
method
には get
, set
, call
が指定でき、取得は get
です。
paths
が path で [[path1], [path2]]
のように複数の path を指定できます。1つの場合は [[path]]
になります。
上にアクセスすると、次のような json が取得できます。
{
"jsonGraph": {
"genrelist": {
"0": {
"$type": "atom"
}
}
}
}
$type
はタイプを表し、atom
はデータを持つオブジェクトを表します。
上記の path には取得するデータのフィールドが指定されていないため、$type
のみ返されました。
genrelist
には name
があるので取得します。
{
"jsonGraph": {
"genrelist": {
"0": {
"name": "Popular on Netflix"
}
}
}
}
さらに titles
もあるので、titles
も取得します。
{
"jsonGraph": {
"genrelist": {
"0": {
"name": "Popular on Netflix",
"titles": {
"$type": "atom"
}
}
}
}
}
なお、["name","titles"]
を2つの path に分けて(["genrelist",0,"name"],["genrelist",0,"titles"])も結果はマージされて同じように出力されます。
次に 0
が指定されている部分で {"from":1,"to":3}
のように指定すると複数取得することができます。
{
"jsonGraph": {
"genrelist": {
"1": {
"name": "Action & Adventure"
},
"2": {
"name": "My List"
},
"3": {
"name": "Goofy TV Shows"
}
}
}
}
JSON Graph
falcor から取得できるデータは json ですが、重複したデータを効率よく扱うため、独自の定義をしています。
上の例で、$type
に atom
とありましたが、全部で3つあります。
-
atom
: データ -
ref
: 参照 -
error
: エラー
参照は重複したデータをまとめるためにあります。
genrelist
の titles
の name
を取得します。
{
"jsonGraph": {
"genrelist": {
"0": {
"titles": {
"0": {
"$type": "ref",
"value": [
"titlesById",
1
]
}
}
},
"1": {
"titles": {
"0": {
"$type": "ref",
"value": [
"titlesById",
8
]
}
}
}
},
"titlesById": {
"1": {
"name": "Curious George"
},
"8": {
"name": "Blitz"
}
}
}
}
title
は複数の genre に登録されていることがあるため、上のように参照型で返すことができます。
この構造は通信量を減らすだけでなく、クライアントでもこの構造で持つことによってメモリを効率的に使うことができます。
最後に
Falcor の基礎的な機能を使ってみました。
まだ、Falcor も GraphQL も十分理解できていませんが、今の印象としては
- クエリーは GraphQL の方が強力
- 取得できるデータの表現は、Falcor の JSON graph の方が強力
です。
検索してみると、すでに GraphSQL vs Falcor のようになっています。(伸びてないですが、ReactJSからこんなポストも)
Facebook と Netflix が強力して組み合わせてはどうでしょうか