GraphQL(Apollo)
6497 ワード
1.基礎
Apolloは、フロントエンドとバックエンドの間の通信層(=a unified graph)を作成するためのプラットフォームです.graphの中心にはGraphQLというquery言語があります.
GraphQLを使うのはいろいろな理由がありますが、その最大の原因はバックエンドAPIがどれだけ変化しても、フロントエンドの観点からは大きな変化はありません.すなわち、バックエンドでAPIに新しいタイプまたはフィールドを容易に追加することができ、クライアントでも新しい追加/変更されたフィールドを容易に使用することができる.それだけでなく,REST APIが2回要求したとしても,GraphQLを用いて1回のクエリが可能な場合が多い.
また、バックグラウンドで最も必要なフィールドのみが提供されるため、ネットワークコストを節約できます.
しかし、GraphQLを使用すると学習コストが増加し、フロントエンドの要件に従ってバックエンドにデータを準備しようとすると、パフォーマンスに悪影響を及ぼす可能性があるため、アーキテクチャの設計が重要です.また、Webブラウザは通常URLに基づいてキャッシュされるが、GraphQLはWebクライアントで使用する場合、同じURLでも異なるクエリーを送信できるため、キャッシュの結果が信じられないという欠点がある.
GraphQLでは、タイプは大体scalar type
とobject type
であり、両者を区別して使用すれば、アーキテクチャを定義する際に大きな困難はありません.また、作成する図でサポートされているクエリーはQueryのspecial type(root type)として宣言でき、サポートされているデータ変更クエリーはMutationのspecial type(root type)として宣言できます.
なお、Queryは複数のサーバを受信したときに同時に実行され、Mutationは順次実行される.すなわち,特定のフィールド値+1を2回行うと,正確には+2となる.これらの部分はGraphQLによって管理されています.詳細については、以下の公式ドキュメントの原文を参照してください...!
A single mutation operation can include multiple top-level fields of the Mutation type. This usually means that the operation will execute multiple back-end writes (at least one for each field). To prevent race conditions, top-level Mutation fields are resolved serially in the order they're listed (all other fields can be resolved in parallel).
2.タイプの種類
GraphQLでは、次のタイプがサポートされています.
(1) Scalar types
一般的なプログラミング言語ではprimitive typeと考えられる.
1) Int: A signed 32-bit intger
2) Float: A signed double-precision floating-point value
3) String: A UTF-8 character sequence
4) Boolean: true or false
5)ID(Serialized as a String):refetchまたはcacheキーとして使用される一意の識別子であり、Stringとして表されるが、読み取り不能である
(2) Object types
GraphQLアーキテクチャで定義したほとんどのタイプはこのタイプです.objecttypeは、それぞれのタイプのフィールドで構成されています.
作成したアーキテクチャ内のすべてのobjecttypeには、対応するobjecttypeの名前をStringに返す__typename
というフィールドが自動的に存在することに注意してください.(ex. Book, Author...)
GraphQLクライアントは、この__typename
をキャッシュに使用するか、または様々なタイプの(unionまたはinterface)フィールドを返すことができるタイプを決定するために使用します.
(3) Query type
このタイプはSpecialobjecttypeと見なすことができる.クライアントがサーバに要求できるクエリーのすべてのtop-levelエントリポイントを示します.
(4) Mutation type
Query typeと同様に、Query typeが可読opeartionのためだけである場合、Mutation typeは書き込み操作に使用される特殊なオブジェクトタイプである.
(5) Input type
Input typeは、フィールドパラメータとして階層化されるデータを提供する特殊なobjectタイプです.たとえば、Input typeは次のように定義できます.input BlogPostContent {
title: String
body: String
media: [MediaDetails!]
}
input MediaDetails {
format: MediaFormat!
url: String!
}
enum MediaFormat {
IMAGE
VIDEO
}
type Mutation {
createBlogPost(content: BlogPostContent!): Post
updateBlogPost(id: ID!, content: BlogPostContent!): Post
}
QueryタイプとMultiタイプの同じフィールドについては、同じInputを共有するよりも、それらを分離することに注意してください.
(6) Enum types
値のタイプは、特定の値からのみ選択できます.enum AllowedColor {
RED
GREEN
BLUE
}
Enumは、任意のスカラータイプで有効な場所に使用できます.それはいつもstringにつながっているからです.
(7) Unions and Interfaces
この2つは抽象タイプであり、GraphQL内の特定のフィールドが異なるobjectタイプで1つ戻ることを可能にします.
(1) Uniton type
union Media = Book | Movie
type Query {
allMedia: [Media] # This list can include both Book and Movie objects
}
Unionに含まれるタイプはobjectタイプでなければなりません.(scalar type X, input type X ...)
unionに含まれるタイプは、必ずしも特定のフィールドを共有する必要はありません.
では、Union typeを返すクエリーについて、どのように要求すればいいのでしょうか.下を見るquery GetSearchResults {
search(contains: "Shakespeare") {
# Querying for __typename is almost always recommended,
# but it's even more important when querying a field that
# might return one of multiple types.
__typename
... on Book {
title
}
... on Author {
name
}
}
}
これにより、各タイプに応じて異なるフィールドを設定できます.(現在はinline fragmentを使用しています)
(2) Interface
名前の通り、インタフェースを使用してインタフェースを実装するタイプには、インタフェース内のすべてのフィールドが含まれている必要があります.interface Book {
title: String!
author: Author!
}
type Textbook implements Book {
title: String!
author: Author!
courses: [Course!]!
}
type ColoringBook implements Book {
title: String!
author: Author!
colors: [String!]!
}
type Query {
books: [Book!]!
}
この場合、bookというクエリーが発行されると、TextBookまたはColoringBookが配列に表示されます.
また、Union typeと同様に、実際のobjecttypeをチェックして、各objecttypeに必要な異なるフィールドを表示することもできます.query GetBooks {
books {
# Querying for __typename is almost always recommended,
# but it's even more important when querying a field that
# might return one of multiple types.
__typename
title
... on Textbook {
courses { # Only present in Textbook
name
}
}
... on ColoringBook {
colors # Only present in ColoringBook
}
}
}
Union typeまたはInterface typeを使用するには、次のように実際のtypeを解析するために__resolveType
という関数を定義する必要があります.const resolvers = {
Book: {
__resolveType(book, context, info){
// Only Textbook has a courses field
if(book.courses){
return 'Textbook';
}
// Only ColoringBook has a colors field
if(book.colors){
return 'ColoringBook';
}
return null; // GraphQLError is thrown
},
},
Query: {
books: () => { ... }
},
};
3. Descriptions(docstrings)
モードには、次のタグ形式のコメントを付けることができます."Description for the type"
type MyObjectType {
"""
Description for field
Supports **multi-line** description for your [API](http://example.com)!
"""
myField: String!
otherField(
"Description for argument"
arg: Int
)
}
4.GraphQL使用時の注意点
(1)GraphQLアーキテクチャは、バックエンドがどのようにデータを格納するかに関係なく、フロントエンドに必要なデータの周りに設計されるべきである.たとえば、各フィールドが実際にサーバに格納されるデータストレージは異なる場合がありますが、フロントエンドはこれらを知る必要はありません.これがGraphQLの目的だからです.
(2)Mutationを使用する場合は,その操作により生成または修正されたデータを応答としてアーキテクチャ設計を行うことが望ましい.これにより、フロントはフォローアップクエリを発行する必要がなく、生成/更新されたデータを表示できます.また、オブジェクトタイプを直接戻りタイプに設定するよりも、type LikePostMutationResponse {
code: String!
success: Boolean!
message: String!
user: User
}
成功/失敗の有無と詳細を含むmetaフィールドをこのように追加して定義することが望ましい.
Reference
この問題について(GraphQL(Apollo)), 我々は、より多くの情報をここで見つけました
https://velog.io/@usaindream/GraphQLApollo
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
GraphQLでは、次のタイプがサポートされています.
(1) Scalar types
一般的なプログラミング言語ではprimitive typeと考えられる.
1) Int: A signed 32-bit intger
2) Float: A signed double-precision floating-point value
3) String: A UTF-8 character sequence
4) Boolean: true or false
5)ID(Serialized as a String):refetchまたはcacheキーとして使用される一意の識別子であり、Stringとして表されるが、読み取り不能である
(2) Object types
GraphQLアーキテクチャで定義したほとんどのタイプはこのタイプです.objecttypeは、それぞれのタイプのフィールドで構成されています.
作成したアーキテクチャ内のすべてのobjecttypeには、対応するobjecttypeの名前をStringに返す
__typename
というフィールドが自動的に存在することに注意してください.(ex. Book, Author...)GraphQLクライアントは、この
__typename
をキャッシュに使用するか、または様々なタイプの(unionまたはinterface)フィールドを返すことができるタイプを決定するために使用します.(3) Query type
このタイプはSpecialobjecttypeと見なすことができる.クライアントがサーバに要求できるクエリーのすべてのtop-levelエントリポイントを示します.
(4) Mutation type
Query typeと同様に、Query typeが可読opeartionのためだけである場合、Mutation typeは書き込み操作に使用される特殊なオブジェクトタイプである.
(5) Input type
Input typeは、フィールドパラメータとして階層化されるデータを提供する特殊なobjectタイプです.たとえば、Input typeは次のように定義できます.
input BlogPostContent {
title: String
body: String
media: [MediaDetails!]
}
input MediaDetails {
format: MediaFormat!
url: String!
}
enum MediaFormat {
IMAGE
VIDEO
}
type Mutation {
createBlogPost(content: BlogPostContent!): Post
updateBlogPost(id: ID!, content: BlogPostContent!): Post
}
QueryタイプとMultiタイプの同じフィールドについては、同じInputを共有するよりも、それらを分離することに注意してください.(6) Enum types
値のタイプは、特定の値からのみ選択できます.
enum AllowedColor {
RED
GREEN
BLUE
}
Enumは、任意のスカラータイプで有効な場所に使用できます.それはいつもstringにつながっているからです.(7) Unions and Interfaces
この2つは抽象タイプであり、GraphQL内の特定のフィールドが異なるobjectタイプで1つ戻ることを可能にします.
(1) Uniton type
union Media = Book | Movie
type Query {
allMedia: [Media] # This list can include both Book and Movie objects
}
Unionに含まれるタイプはobjectタイプでなければなりません.(scalar type X, input type X ...)unionに含まれるタイプは、必ずしも特定のフィールドを共有する必要はありません.
では、Union typeを返すクエリーについて、どのように要求すればいいのでしょうか.下を見る
query GetSearchResults {
search(contains: "Shakespeare") {
# Querying for __typename is almost always recommended,
# but it's even more important when querying a field that
# might return one of multiple types.
__typename
... on Book {
title
}
... on Author {
name
}
}
}
これにより、各タイプに応じて異なるフィールドを設定できます.(現在はinline fragmentを使用しています)(2) Interface
名前の通り、インタフェースを使用してインタフェースを実装するタイプには、インタフェース内のすべてのフィールドが含まれている必要があります.
interface Book {
title: String!
author: Author!
}
type Textbook implements Book {
title: String!
author: Author!
courses: [Course!]!
}
type ColoringBook implements Book {
title: String!
author: Author!
colors: [String!]!
}
type Query {
books: [Book!]!
}
この場合、bookというクエリーが発行されると、TextBookまたはColoringBookが配列に表示されます.また、Union typeと同様に、実際のobjecttypeをチェックして、各objecttypeに必要な異なるフィールドを表示することもできます.
query GetBooks {
books {
# Querying for __typename is almost always recommended,
# but it's even more important when querying a field that
# might return one of multiple types.
__typename
title
... on Textbook {
courses { # Only present in Textbook
name
}
}
... on ColoringBook {
colors # Only present in ColoringBook
}
}
}
Union typeまたはInterface typeを使用するには、次のように実際のtypeを解析するために__resolveType
という関数を定義する必要があります.const resolvers = {
Book: {
__resolveType(book, context, info){
// Only Textbook has a courses field
if(book.courses){
return 'Textbook';
}
// Only ColoringBook has a colors field
if(book.colors){
return 'ColoringBook';
}
return null; // GraphQLError is thrown
},
},
Query: {
books: () => { ... }
},
};
3. Descriptions(docstrings)
モードには、次のタグ形式のコメントを付けることができます."Description for the type"
type MyObjectType {
"""
Description for field
Supports **multi-line** description for your [API](http://example.com)!
"""
myField: String!
otherField(
"Description for argument"
arg: Int
)
}
4.GraphQL使用時の注意点
(1)GraphQLアーキテクチャは、バックエンドがどのようにデータを格納するかに関係なく、フロントエンドに必要なデータの周りに設計されるべきである.たとえば、各フィールドが実際にサーバに格納されるデータストレージは異なる場合がありますが、フロントエンドはこれらを知る必要はありません.これがGraphQLの目的だからです.
(2)Mutationを使用する場合は,その操作により生成または修正されたデータを応答としてアーキテクチャ設計を行うことが望ましい.これにより、フロントはフォローアップクエリを発行する必要がなく、生成/更新されたデータを表示できます.また、オブジェクトタイプを直接戻りタイプに設定するよりも、type LikePostMutationResponse {
code: String!
success: Boolean!
message: String!
user: User
}
成功/失敗の有無と詳細を含むmetaフィールドをこのように追加して定義することが望ましい.
Reference
この問題について(GraphQL(Apollo)), 我々は、より多くの情報をここで見つけました
https://velog.io/@usaindream/GraphQLApollo
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
"Description for the type"
type MyObjectType {
"""
Description for field
Supports **multi-line** description for your [API](http://example.com)!
"""
myField: String!
otherField(
"Description for argument"
arg: Int
)
}
(1)GraphQLアーキテクチャは、バックエンドがどのようにデータを格納するかに関係なく、フロントエンドに必要なデータの周りに設計されるべきである.たとえば、各フィールドが実際にサーバに格納されるデータストレージは異なる場合がありますが、フロントエンドはこれらを知る必要はありません.これがGraphQLの目的だからです.
(2)Mutationを使用する場合は,その操作により生成または修正されたデータを応答としてアーキテクチャ設計を行うことが望ましい.これにより、フロントはフォローアップクエリを発行する必要がなく、生成/更新されたデータを表示できます.また、オブジェクトタイプを直接戻りタイプに設定するよりも、
type LikePostMutationResponse {
code: String!
success: Boolean!
message: String!
user: User
}
成功/失敗の有無と詳細を含むmetaフィールドをこのように追加して定義することが望ましい.Reference
この問題について(GraphQL(Apollo)), 我々は、より多くの情報をここで見つけました https://velog.io/@usaindream/GraphQLApolloテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol