Share
Embed
GraphQL入門
s-ichikawa
January 26, 2019
Transcript
69 slides
-
仙台 お問い合わせ対応 商品監視 etc... 福岡 電話対応 etc... 東京 プロダクトチーム コーポレート
etc... メルカリと仙台 -
今日話すこと - GraphQLとは? - Schema と Query - GraphQLは銀の弾丸? -
Library, Tool & Services - GraphQLの初め方 -
Multi Client + Restful API Browser User iOS Android News
Transaction Todo -
Restful APIの問題 エンドポイントにまつわる問題 - Round Tripが増える - 対応漏れが発生しやすくなる(セキュリティ系とか) Responseがどのようなデータ構造をしているのか予測が付きづらい -
https://example.com/user/123 をGETしたときに返されるResponseはどんな データ構造をもっているか分からない Over Fetching - レスポンスの中に使わないデータが含まれている状態 Under Fetching - レスポンス中に必要なデータが含まれていない状態 -
GraphQLはどう課題解決するか - エンドポイントが増えすぎて管理が煩雑に - 単一エンドポイント - Round Tripが多い - Over
Fetching, Under Fetching - 1つのクエリで複数のリソースを取得できるため、 1回の Round Tripで必要な情報が過不足なく取得可能 - RequestとResponseのデータ構造の乖離 - GraphQLではQueryとResponseの構造が酷似しているの で理解しやすい -
GraphQLの強み - Schemaによる恩恵 - Schema first development - Documentなども自動生成がしやすい -
IDEなどで補助機能が使える - 開発補助ツール等が豊富 - 学習コストが低い - QueryもSchemaも覚えることはそんなに多くない -
History of GraphQL 2012.xx Facebookで開発が始まる 2015.9 React.js Confでtechnical previewとして公開 2016.9
technical previewをやめて正式に公開 同タイミングでGitHubのAPI v4がGraphQL APIとして公開 2018.11 GraphQL PJの運営がFacebookからGraphQL Foundationへ -
query GetUser { user(id: "U12345abcde") { id name } }
{ "data": { "user": { "id": "U12345abcde", "name": "s-ichikawa" } } } type User { id: ID! name: String! } type Query { user(id: String): User } Schema Query Response GraphQL POST https://example.com/query -
query GetUser { user(id: "U12345abcde") { id name items (first:
2) { id name price } } } "data": { "user": { "id": "U12345abcde", "name": "s-ichikawa", "items": [ { "id": "I8674665223082153551", "name": "ほうじ茶", "price": 500 }, { "id": "I6129484611666145821", "name": "烏龍茶", "price": 500 } ] } } } Response -
query GetUser { items { id name price } user(id:
"U12345abcde") { id name } } { "errors": [ { "message": "failed to access db", "path": [ "items" ] } ], "data": { "items": null, "user": { "id": "U12345abcde", "name": "s-ichikawa" } } } Error Response -
Backend実装の流れ 1. Schema設計する 2. 追加・変更されたSchema毎にResolverを書く Resolver? - Queryで要求されたType(型)を解決するもの。 - DBや外部APIをコールするなどしてデータを用意して型を解決して返す
- Resolverは定義した型毎に作る、この集合がサーバ実装となる - 作り方は使うLibraryに寄る -
Object Type - type キーワードを使用して宣言 - { }内にFieldを記載していく - Fieldは
名前: 型名という形で宣言 - Object TypeかScalar Type、 enumが指定可能 - ! はNon Nullable指定 - [ ] はArray - 型やFieldには “(double quote) で ドキュメントが書ける “”” Our Service User “”” type User { id: ID! name: String! follower: [User!] } -
Scalar Type - 基本となるScalarはたったの5種類 - Int - Float - String
- Boolean - ID - 必要に応じてCustom Scalarも作 れる “”” Default Scalarは宣言する必要なし “”” scalar Timestamp type Item { id: ID! name: String! createdAt: Timestamp! updatedAt: TimeStamp! } -
Enum - ステータスやカテゴリなどの定数を 宣言できる - enumキーワードを使用して表現す る - ScalarやObject Typeと同様に
フィールドの型として設定すること ができる enum ItemStatus { DRAFT ON_SALE TRADING SOLD CANCEL } type Item { id: ID! name: String! status: ItemStatus! } -
ArrayにおけるNullableの表現 配列内の値がNull 配列自体がNull [User] OK OK [User!] NG OK [User]!
OK NG [User!]! NG NG -
Operation Type - GraphQL APIとしてリクエスト可能な オペレーションについて宣言する - 宣言できるオペレーションは3種 - query
- mutation - subscription schema { query: Query mutation: Mutation } type Query { users: [User!] } type Mutation { registoration(name: String!): User } -
Input Type - Query呼び出し時に複雑なデータを 渡したい場合にそれを型として宣言 しておくことができる - 通常のtypeとほぼ同様だがこちらは inputキーワードを使う -
入力値が多い場合などに使うと Schemaの見通しが良くなる - 返り値として設定することはできない mutation { register(name: String!, email: String!, gender: Gender, address: String!): User } ↓ input RegisterInput { name: String! email: String! gender: Gender address: String! } mutation { register(input: RegisterInput): User } -
Interface - 指定した型に、特定のフィールドを 持つことを約束させる為に使用す る interface Transaction { id: ID!
item: Item! } type SellingTransction implements Transaction { id: ID! item: Item! } type CancelTransaction implements Transaction { id: ID! item: Item! reason: String } query { transactions: [Transaction] } -
Union - 異なる複数の型の内のいずれかの 型 - 全く異なるフィールドを持つ型を1つ の型として表現したい場合に使用 する type News
{ title: String! content: String! } type Todo { title: String! description: String } type Message { subject: String! body: String } union Notification = News | Todo | Message -
GraphQLのクエリ言語 - GraphQL APIを通してデータの取得や登録・更新を行う為の言語 - Operationは大きく別けて3種類がある(ルートOperation型) - Query - Mutation
- Subscription - 複数のOperationを1度にリクエストすることは出来ない -
query GetUser { user(id: "U12345abcde") { id name follower {
name } } } { "data": { "user": { "id": "U12345abcde", "name": "ichikawa", "follower": [ {“friend01”}, {“friend02”}, ], } } } type User { id: ID! name: String! follower: [User] } type Query { user(id: String): User } Schema http://example.com/query -
query { user { id name email follower { id
name email } } } query { user { ...userInfo follower { ...userInfo } } } flagment userInfo on User { user_id: id name email } -
mutation Registration { registration (name: "s-ichikawa") { id name }
} { "data": { "user": { "id": "U12345abcde", "name": "s-ichikawa" } } } type User { id: ID! name: String! } type Mutation { registration(name: String): User } http://example.com/query -
query { __type(name: "User") { name fields { name }
} } { "data": { "__type": { "name": "User", "fields": [ { "name": "id" }, { "name": "name" } ] } } } type User { id: ID! name: String! } http://example.com/query -
Directive - SchemaやQueryに対して付加情 報を与える事ができる - GraphQLの仕様として組み込まれ ているのは - Schemaで使える :@deprecated
- Queryで使える:@skip, @include - ライブラリが対応していれば独自の Directiveも作れる “”” in Schema “”” type User { id: ID! name: String! sex: Sex @deprecated } # in Query query myQuery($someTest: Boolean) { experimentalField @skip(if: $someTest) } -
GraphQLが抱える課題 - N+1問題 - 情報をまとめて遅延取得する方法などを使わないと容易に N+1問題が発生する - ファイルアップロード - 別途RESTエンドポイント作るという手法が今の所よく聞く
- モニタリング - 単一エンドポイントかつ基本的に 200が返るためRestful APIの時とはモニタリングの仕方が全く異 なる - Cache - 単一エンドポイントかつ基本的に POSTを使用するためCDNでCacheするのがちょっと面倒 (できなくはない) GraphQLは銀の弾丸ではない。 Restfulの方がやりやすい時はRestfulを使いましょう。 -
Server Libraries - JavaScript - GraphQL.js - express-graphql - Apollo-Server
- PHP - graphql-php FWに依存しない形で使うならこれ - Lighthouse Laravelを使っているならこれが活発で良さげ - Java, Go, Ruby, Python, Elixir, Erlang, etc... -
Client Libraries - JavaScript - Apollo-Client - Relay - Swift
/ Objective-C (iOS) - Apollo iOS - GraphQL iOS - Java (Android) - Apollo Android - Nodes - C#, Go, python -
GraphQL IDE - In-browser - GraphiQL https://github.com/skevy/graphiql-app - GraphQL Playground
https://github.com/prisma/graphql-playground - Software - Insomnia https://insomnia.rest/graphql/ - Altair GraphQL Client https://github.com/imolorhe/altair -
その他 - IDE Plugin - for IntelliJ https://github.com/jimkyndemeyer/js-graphql-intellij-plugin - for
VSCode https://marketplace.visualstudio.com/items?itemName=Prisma.vscode-graphql - Schema関連 - graphdoc https://github.com/2fd/graphdoc - graphql-doctor https://github.com/cap-collectif/graphql-doctor - Test - graphql-faker https://github.com/APIs-guru/graphql-faker -
まずは触ってみる - 既にあるGraphQL APIを触ってみる - GitHub API v4 - SW
API - ここから色々探せます http://apis.guru/graphql-apis/ - 作ってみる - 簡単なサンプル - 既存APIをの一部をGraphQLに置き換えてみる -
役立つリンク - Introduction to GraphQL https://graphql.org/learn/ - 「GraphQL」徹底入門 ─ RESTとの比較、API・フロント双方の実装から学ぶ
https://employment.en-japan.com/engineerhub/entry/2018/12/26/103000#GraphQL%E3%81%A8% E3%81%AF%E4%BD%95%E3%81%8B