overview
{
"data": {
"human": {
"id": 1000,
"name": "Luke Skywalker",
"height": 172
}
}
}
Response
query {
findHuman {
human(id: "1000") {
id
name
height
}
}
}
Request
(GET )
Request
mutation CreateHuman($name: String!, $height: Int!) {
createHuman(name: $name, height: $height) {
id
name
height
}
}
Variables
{
"name": "Jay Chou",
"height": 174,
}
(UPDATE)
Request
mutation CreateHuman($name: String!, $height: Int!) {
createHuman(name: $name, height: $height) {
id
name
height
}
}
Variables
{
"name": "Jay Chou",
"height": 174,
}
{
"data": {
"human": {
"id": 1001,
"name": "Jay Chou",
"height": 174
}
}
}
Response
(UPDATE)
Request
mutation CreateHuman($name: String!, $height: Int!) {
createHuman(name: $name, height: $height) {
id
name
height
}
}
Variables
{
"name": "Jay Chou",
"height": 174,
}
{
"data": {
"human": {
"id": 1001,
"name": "Jay Chou",
"height": 174
}
}
}
Response
(UPDATE)
Subscription/Fragment/Directive......etc
GraphQL Doc
src: https://chanakaudaya.medium.com/graphql-based-solution-architecture-patterns-8905de6ff87e
query {
findHuman {
human(id: "1000") {
id
name
height
}
}
}
gql
src: https://chanakaudaya.medium.com/graphql-based-solution-architecture-patterns-8905de6ff87e
query {
findHuman {
human(id: "1000") {
id
name
height
}
}
}
gql
gql
1. write gql with the corresponding library
gql
/graphql
2. send request via a single URL/endpoint
gql
3. resolve gql, get/update data with the corresponding library
Post method with JSON Payload
define Object/write Resolvers
type Human {
id: ID!
name: String!
height: Int!
clubs: [Club]
}
type Club {
id: ID!
name: String!
}
Object Type
Int
Float
String
Boolean
ID
(Default) Scalar Types
(Custom) Scalar Types
scalar Date
just like define ORM entity to some degree 🤔
Query: {
human(obj, args, context, info) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
}
This example is written in JavaScript, however GraphQL servers can be built in many different languages.
Resolver
src: https://chanakaudaya.medium.com/graphql-based-solution-architecture-patterns-8905de6ff87e
src: https://chanakaudaya.medium.com/graphql-based-solution-architecture-patterns-8905de6ff87e
{
"data": {
"__schema": {
"types": [
{
"name": "Query"
},
{
"name": "String"
},
{
"name": "ID"
},
{
"name": "Mutation"
},
{
"name": "Episode"
},
{
"name": "Character"
},
{
"name": "Int"
},
{
"name": "LengthUnit"
},
{
"name": "Human"
},
{
"name": "Float"
},
{
"name": "Droid"
},
{
"name": "FriendsConnection"
},
{
"name": "FriendsEdge"
},
{
"name": "PageInfo"
},
{
"name": "Boolean"
},
{
"name": "Review"
},
{
"name": "ReviewInput"
},
{
"name": "Starship"
},
{
"name": "SearchResult"
},
{
"name": "__Schema"
},
{
"name": "__Type"
},
{
"name": "__TypeKind"
},
{
"name": "__Field"
},
{
"name": "__InputValue"
},
{
"name": "__EnumValue"
},
{
"name": "__Directive"
},
{
"name": "__DirectiveLocation"
}
]
}
}
}
Response
query {
__schema {
types {
name
}
}
}
Request
.gql easy to understand
query {
findHuman {
human(id: "1000") {
id
name
height
clubs {
id
name
}
}
}
}
nested data
query {
findHuman {
human(id: "1000") {
id
name
height
clubs {
id
name
}
}
}
}
nested data
Less time spent documenting and navigating APIs
Let's talk about REST first
In REST comes with some downsides like:
In REST comes with some downsides like:
query {
findHuman {
human(id: "1000") {
id
name
height
clubs {
id
name
}
}
project (id: '123') {
id
name
}
}
}
REST
https://www.howtographql.com/basics/1-graphql-is-the-better-rest
multi request
GraphQL
https://www.howtographql.com/basics/1-graphql-is-the-better-rest
single request
Over-fetching: Downloading superfluous data
Under-fetching and the n+1 problem
https://www.howtographql.com/basics/1-graphql-is-the-better-rest
This is a trade off, but here come some solution ......
We will explain later🤪
more code/more library to learn/more bundle size/securitiy issue
If front-end dev not familiar with graphQL schema,
he/she will get useless field and cost performance
-> trigger fieldResolver
more code/more library to learn/more bundle size/securitiy issue
more code/more library to learn/more bundle size/securitiy issue
Introspection/Authorize issue
By providing many endpoints, a REST API enables easy web caching configurations to match certain URL patterns, HTTP methods, or specific resources.
Due to having only one endpoint with many different queries, it’s much harder to use this type of caching with a GraphQL API.
Apollo Tech-talk: Simple caching, made difficult
Responses to [the POST] method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields
You can't use GET since query parameters have size limits!
狠角色
Application/Network
export default function request(url, query, variables) {
return fetch(`${url}?query=${query}&variables=${variables}`)
.then(result => {
if (result.status !== 414) {
return result;
}
return fetch(url, {
method: 'POST',
body: JSON.stingify({ query, variables })
});
})
}
Apollo Persist Queries
Apollo Client stores the results of your GraphQL queries in a local, normalized, in-memory cache.
This enables Apollo Client to respond almost immediately to queries for already-cached data, without even sending a network request.
manage API state
Globally Unique ID: _typename + id
{
"__typename": "Person",
"id": "cGVvcGxlOjE=",
"name": "Luke Skywalker",
"homeworld": {
"__typename": "Planet",
"id": "cGxhbmV0czox",
"name": "Tatooine"
}
}
{
"__typename": "Person",
"id": "cGVvcGxlOjE=",
"name": "Luke Skywalker",
"homeworld": {
"__ref": "Planet:cGxhbmV0czox"
}
}
{
"__typename": "Person",
"id": "cGVvcGxlOjE=",
"name": "Luke Skywalker",
"homeworld": {
"__typename": "Planet",
"id": "cGxhbmV0czox",
"name": "Tatooine"
}
}
{
"__typename": "Person",
"id": "cGVvcGxlOjE=",
"name": "Luke Skywalker",
"homeworld": {
"__ref": "Planet:cGxhbmV0czox"
}
}
Globally Unique ID: _typename + id
type Post {
id: ID!
title: String
author: Author
votes: Int @cacheControl(maxAge: 30)
comments: [Comment]
readByCurrentUser: Boolean! @cacheControl(maxAge: 10, scope: PRIVATE)
}
schema
Whenever Apollo Server sends an operation response that has a non-zero maxAge, it includes a Cache-Control HTTP header that describes the response's cache policy.
Cache-Control: max-age=60, private
HTTP header format
query {
food {
title
}
}
query {
food {
title
body
}
}
query {
# with comments
food {
title
}
}
generate different cache keys -> In reality
not smart enough 😢
Another cache issue solution: GraphQL CDN
creator of Styled Component
More Info -> https://graphcdn.io
投資了酒吧,在信義安和捷運站旁邊,歡迎大家蒞臨😎