overview of graphql & clients

94
Overview of GraphQL & Clients ! # @zetavg fb.me/pokaichang72

Upload: pokai-chang

Post on 28-Jan-2018

75 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Overview of GraphQL & Clients

Overview ofGraphQL & Clients

! # @zetavgfb.me/pokaichang72

Page 2: Overview of GraphQL & Clients

My Background⬢ Building stuff as a web developer from

2012 ⬢ Shallow experiences covered from

design, mobile, front-end and backend develop to cloud deployments (AWS)

⬢ Fan of GraphQL/Relay of its beauty of API design since 2015

⬢ Working at with Ruby, JavaScript (React.js) and playing Elixir

⬢ Former tech lead at Colorgy

! # @zetavgfb.me/pokaichang72

Page 3: Overview of GraphQL & Clients

⬡ Complain about RESTful Introduce GraphQL

⬡ Just enough GraphQL to get started

⬡ GraphQL client library overview

⬡ Intro to Relay

⬡ Demo: GraphQL & Relay on Railshttps://github.com/zetavg/RailsRelayTodoMVC

Outline

Page 4: Overview of GraphQL & Clients

Background of API Developing

Page 5: Overview of GraphQL & Clients

The evolution of API⬢ RESTful: Easy to use, easy to develop

⬡ Directly based on Wide World Web

⬡ URI as resource name (noun), HTTP method as action (verb)

⬡ We need documents: Swagger...

⬡ ...and type definitions: JSON Schema

⬡ ...and data relations: JSON API

⬡ Combine them all: API Blueprint, RAML

Page 6: Overview of GraphQL & Clients

The evolution of API⬢ But for the front-end, especially SPA or mobile apps:

⬡ Querying complex data efficiently is still hard

⬡ We may come up with lots of endpoint versions

⬡ Or messy features on different endpoints

⬡ On purpose specs are hard to follow, without an clear interface, APIs tends to be hard to reuse and maintain

⬡ Writing code to fetch and store data is annoying

⬡ Caching is hard cause there's no explicit schema

⬡ Co-working may be messy cause there's no schema

Page 7: Overview of GraphQL & Clients

/api/v1/posts.json

/api/v2/posts.json

/api/v3/posts.json

/api/v4/posts.json

/api/v65535/posts.json

⋯⋯

Page 8: Overview of GraphQL & Clients

/api/posts.json

/api/posts.json?include=author

/api/posts.json?include=author,comments

/api/posts.json?cover=true&include=author,comments

/api/posts.json?cover=true&include=author,comments_with_author

Page 9: Overview of GraphQL & Clients

API should be like this

Page 10: Overview of GraphQL & Clients

Not this

Page 11: Overview of GraphQL & Clients

GraphQL⬢ A new query language

⬢ Brief History:

⬡ 2012 - Used for Facebook mobile app

⬡ 2015 - Publicly released

⬡ 2017 - Now: GraphQL & Relay re-licensed under     MIT

⬢ Normally uses a single endpoint URL ( POST /graphql )

Page 12: Overview of GraphQL & Clients

A Glance on GraphQL

Page 13: Overview of GraphQL & Clients

All your application data can be represented as a graph

Page 14: Overview of GraphQL & Clients

$

{ "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

$

{ "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌] }

$

{ "name": "Jasper", "bio":"...", "followers": [◌], "repos": [◌] }

$

{ "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Hello World", "description": "...", "stargazers": [◌, ◌] }

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

!{ "name": "Awesome App", "description": "...", "stargazers": [◌] }

!{ "name": "Todo", "description": "...", "stargazers": [◌] }

!

{ }{ "viewer": ◌ }

Page 15: Overview of GraphQL & Clients

A subset of the graph is used to show an UI

Page 16: Overview of GraphQL & Clients

$

{ "name": "Jasper", "bio":"...", "followers": [◌], "repos": [◌] }

$

{ "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌] }

$

{ "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌] }

!{ "name": "Awesome App", "description": "...", "stargazers": [◌] }

!{ "name": "Todo", "description": "...", "stargazers": [◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

{ }{ "viewer": ◌ }

$

{ "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

$ dddddddd

Page 17: Overview of GraphQL & Clients

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

!{ "name": "Awesome App", "description": "...", "stargazers": [◌] }

!{ "name": "Todo", "description": "...", "stargazers": [◌] }

{ }{ "viewer": ◌ }

$

{ "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

$

{ "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌] }

$

{ "name": "Jasper", "bio":"...", "followers": [◌], "repos": [◌] }

$

{ "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌] }

$$

$

$

$

$

Page 18: Overview of GraphQL & Clients

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

$

{ "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌] }

!{ "name": "Awesome App", "description": "...", "stargazers": [◌] }

!{ "name": "Todo", "description": "...", "stargazers": [◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

{ }{ "viewer": ◌ }

$ $ $

$ $ $

$ $ $

$ $

/

$

{ "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌] }

$

{ "name": "Jasper", "bio":"...", "followers": [◌], "repos": [◌] }

$

{ "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

Page 19: Overview of GraphQL & Clients

$

{ "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

$

{ "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌] }

$

{ "name": "Jasper", "bio":"...", "followers": [◌], "repos": [◌] }

$

{ "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Hello World", "description": "...", "stargazers": [◌, ◌] }

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

!{ "name": "Awesome App", "description": "...", "stargazers": [◌] }

!{ "name": "Todo", "description": "...", "stargazers": [◌] }

!

{ }{ "viewer": ◌ }

GraphQL

Page 20: Overview of GraphQL & Clients

⬡ Complain about RESTful Introduce GraphQL

⬡ Just enough GraphQL to get started

⬡ GraphQL client library overview

⬡ Intro to Relay

⬡ Demo: GraphQL & Relay on Railshttps://github.com/zetavg/RailsRelayTodoMVC

Outline

Page 21: Overview of GraphQL & Clients

Basic Query⬢ Starts with selecting fields on the query root ⬢ WYSIWYG

{ "data": { "viewer": { "name": "Pokai Chang" } } }

query { viewer { name } }

Page 22: Overview of GraphQL & Clients

Basic Query⬢ Querying nested fields

{ "data": { "viewer": { "name": "Pokai Chang", "birthday": { "month": 7, "day": 2 } } } }

query { viewer { name birthday { month day } } }

Page 23: Overview of GraphQL & Clients

Types⬢ Get the type of a object using the __typename

meta field

{ "data": { "viewer": { "__typename": "User", "birthday": { "__typename": "Date" } } } }

query { viewer { __typename birthday { __typename } } }

Page 24: Overview of GraphQL & Clients

Type defs as docs# GraphQL query language query { viewer { name birthday { month day } following { name } } }

# GraphQL schema language type Query { viewer: User }

type User { name: String! birthday: Date followers: [User] following: [User] }

type Date { year: Integer month: Integer day: Integer }

Page 25: Overview of GraphQL & Clients

Non-Null & Lists# GraphQL schema language type Query { viewer: User }

type User { name: String! birthday: Date followers: [User] following: [User] }

type Date { year: Integer month: Integer day: Integer }

[<thing>] means an array of <thing> objects

! means that the field is non-nullable

Page 26: Overview of GraphQL & Clients

Arguments⬢ Arguments can be defined on fields

query { user(id: 1) { name } }

Page 27: Overview of GraphQL & Clients

Arguments⬢ Nested fields also can have arguments

query { user(id: 1) { name repo(name: "awesome-graphql") { name description } } }

Page 28: Overview of GraphQL & Clients

Variables⬢ A way to dynamically change arguments for fields

query ($userId: Int!, $repoName:String!) { user(id: $userId) { name repo(name: $repoName) { name description } } }

{ "userId": 1, "repoName": "awesome-graphql" }

+

Page 29: Overview of GraphQL & Clients

Fragment

fragment profileFields on User { name bio avatarUrl }

query { viewer { ...profileFields }

user(id: 1) { ...profileFields } }

Pre-define a set of fieldson a type or interface

as meaningful fragment

Page 30: Overview of GraphQL & Clients

Interfaces⬢ An abstract type that includes a set of fields that a

type must define to implement

⬢ Can be used for fragments

interface Actor { id: ID! name: String! avatarUrl: String! }

type User implements Actor { id: ID! name: String! avatarUrl: String! ... }

type Bot implements Actor { id: ID! name: String!

# Sample Query

fragment actorFields on Actor { name bio avatarUrl }

query { feed { actor { ...actorFields } verb object {

Page 31: Overview of GraphQL & Clients

Mutate Data w/ Mutations⬢ Mutation queries lives under mutation instead of

query , and are ways how we can change the data ⬢ We can put the input data in arguments, changed

nodes will be returned in the selectable payload ⬢ It’s a convention like RESTful GET/POST that clients

rely on

mutation { addComment(input: { subjectId: 1, body: "Hi." }) { subject { comments { body } } } }

Page 32: Overview of GraphQL & Clients

Input Types⬢ Yes, inputs are also typed

input AddCommentInput { subjectId: ID! body: String! }

mutation { addComment(input: { subjectId: 1, body: "Hi." }) { subject { comments { body } } } }

Page 33: Overview of GraphQL & Clients

GraphiQL⬢ An open source GraphQL playground

Page 34: Overview of GraphQL & Clients

Query tree⬢ Each query is a tree extracted from the graph

⬢ The query is resolved by traversing the tree and resolving each field

query { viewer { name bio repos { name description } } }

Page 35: Overview of GraphQL & Clients

$

{ "name": "Jasper", "bio":"...", "followers": [◌], "repos": [◌] }

$

{ "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌]

$

{ "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌] }

!{ "name": "Awesome App", "description": "...", "stargazers": [◌] }

!{ "name": "Todo", "description": "...", "stargazers": [◌] }

!

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

{ }{ "viewer": ◌ }

$

{ "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

Query tree

Page 36: Overview of GraphQL & Clients

Query tree

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

{ }{ "viewer": ◌ }

${ "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

Page 37: Overview of GraphQL & Clients

graphql.org

Page 38: Overview of GraphQL & Clients

⬡ Complain about RESTful Introduce GraphQL

⬡ Just enough GraphQL to get started

⬡ GraphQL client library overview

⬡ Intro to Relay

⬡ Demo: GraphQL & Relay on Railshttps://github.com/zetavg/RailsRelayTodoMVC

Outline

Page 39: Overview of GraphQL & Clients

Fetching Pagination

Caching Update

Optimistic Update Realtime UI

Page 40: Overview of GraphQL & Clients
Page 41: Overview of GraphQL & Clients

Fetching

Page 42: Overview of GraphQL & Clients
Page 43: Overview of GraphQL & Clients

const View = (data) => UI

Page 44: Overview of GraphQL & Clients

Redux data flow

View

State

subscribe

Redux Store

Page 45: Overview of GraphQL & Clients

Redux data flow

View

State

ReducerAction

subscribe

prevState

Page 46: Overview of GraphQL & Clients

Redux data flow

View

State

ReducerAction

subscribe

prevState

Backend ?

Page 47: Overview of GraphQL & Clients

Redux data flow

View

State

ReducerAction

subscribe

prevState

Backend

Action

Action

Action

Page 48: Overview of GraphQL & Clients

$

{ "name": "Neson", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌] }

$

{ "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌] }

$

{ "name": "Jasper", "bio":"...", "followers": [◌], "repos": [◌] }

$

{ "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌] }

!{ "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌] }

!{ "name": "Hello World", "description": "...", "stargazers": [◌, ◌] }

!{ "name": "Handy Util", "description": "...", "stargazers": [◌] }

!{ "name": "Awesome App", "description": "...", "stargazers": [◌] }

!{ "name": "Todo", "description": "...", "stargazers": [◌] }

!

{ }{ "viewer": ◌ }

GraphQL

Page 49: Overview of GraphQL & Clients

Relay data fetching

View

$$

$ $

$

dd

$ $ $ $

dddddd

Relay Store

Page 50: Overview of GraphQL & Clients

Relay data fetching

viewer { name bio }

Viewdddddddd

viewer { repos { name description } }

$

Relay Store

Page 51: Overview of GraphQL & Clients

Relay data fetching

Viewdddddddd

viewer { repos { name description } }

Backend

query { viewer { name bio repos { name description } } }

$

Relay Store

viewer { name bio }

Page 52: Overview of GraphQL & Clients

Relay data fetching

Viewdddddddd

viewer { repos { name description } }

Backend{ "data": { "viewer": { "name": "…", "bio": "…", "followers": […], "repos": […] } } }

$

viewer { name bio }

query { viewer { name bio repos { name description } } }

Page 53: Overview of GraphQL & Clients

Relay data fetching

View

$ㄎㄎㄎㄎ

viewer { repos { name description } }

dddddddd

viewer { name bio }

Page 54: Overview of GraphQL & Clients

View

Relay data fetching

viewer { name bio }

View

$ㄎㄎㄎㄎ

viewer { following { name } }

dddddddd

$

$

$

$

$

Page 55: Overview of GraphQL & Clients

View

Relay data fetching

viewer { name bio }

View

$ㄎㄎㄎㄎ

viewer { following { name } }

dddddddd

$

$

$

$

$

Backend

query { viewer { following { name } } }

{ "data": { "viewer": { "following": […] } } }

Page 56: Overview of GraphQL & Clients

View

Relay data fetching

viewer { name bio }

View

$ㄎㄎㄎㄎ

viewer { following { name } }

dddddddd

$

$

$

$

$ㄎㄎㄎㄎ

Page 57: Overview of GraphQL & Clients

Caching

Page 58: Overview of GraphQL & Clients

Query treequery { user(login: "zetavg") { name repositories { name } } }

{ "data": { "user": { "name": "Pokai Chang", "repositories": [ { "name": "dotfiles" }, { "name": "Thing" }, { "name": "Stuff" } ] } } }

Page 59: Overview of GraphQL & Clients

Query treeQuery Root

User

Repo Repo Repo

name

user(login: "zetavg")

"Pokai Chang"

"dotfiles"

name repositories

name

"Thing"

name

"Stuff"

query { user(login: "zetavg") { name repositories { name } } }

{ "data": { "user": { "name": "Pokai Chang", "repositories": [ { "name": "dotfiles" }, { "name": "Thing" }, { "name": "Stuff" } ] } } }

Page 60: Overview of GraphQL & Clients

Caching the query result

⬢ Strategy 1: traverse path

Query Root

user(login: "zetavg")

User

Repo Repo Repo

name

"Pokai Chang"

"dotfiles"

name repos

name

"Thing"

name

"Stuff"

⬡ Same path, same object

Page 61: Overview of GraphQL & Clients

⬢ Strategy 1: traverse path

Query Root

user(login: "zetavg")

User

Repo Repo Repo

name

"Pokai Chang"

"dotfiles"

name repos

name

"Thing"

name

"Stuff"

user(login: "zetavg")

user(login: "zetavg")/repos[2]

⬡ Same path, same object

Caching the query result

Page 62: Overview of GraphQL & Clients

⬢ Strategy 1: traverse path

Query Root

user(login: "zetavg")

User

Repo Repo Repo

name

"Pokai Chang"

"dotfiles"

name repos

name

"Thing"

name

"Stuff"

repo(owner: "zetavg", name: "dotfiles")

Repo

name

"dotfiles"

⬡ Sometimes path assumption isn’t enough

Caching the query result

Page 63: Overview of GraphQL & Clients

⬢ Strategy 1: traverse path

Query Root

user(login: "zetavg")

User

Repo Repo Repo

name

"Pokai Chang"

"dotfiles"

name repos

name

"Thing"

name

"Stuff"

repo(owner: "zetavg", name: "dotfiles")

Repo

name

"dotfiles"

Same object on different path

⬡ Sometimes path assumption isn’t enough

Caching the query result

Page 64: Overview of GraphQL & Clients

⬢ Strategy 1: traverse path

⬢ Strategy 0: object identifier

repo/dotfiles

Repo

name

"dotfiles"

repo/dotfiles

Repo

name

"dotfiles"

Query Root

User

Repo Repo

user(login: "zetavg")

"Pokai Chang"

name repos

name

"Thing"

name

"Stuff"

repo(owner: "zetavg", name: "dotfiles")

repo/Thing repo/Stuff

Caching the query result

Page 65: Overview of GraphQL & Clients

⬢ Strategy 1: traverse path

⬢ Strategy 0: object identifier

Query Root

User

Repo Repo

user(login: "zetavg")

"Pokai Chang"

name repos

name

"Thing"

name

"Stuff"

repo(owner: "zetavg", name: "dotfiles")

repo/Thing repo/Stuff

Repo

name

"dotfiles"

repo/dotfiles

Caching the query result

Page 66: Overview of GraphQL & Clients

⬢ Strategy 1: traverse path

⬢ Strategy 0: object identifier

⬡ Relay: we need the server to give a global id for nodes that need to be identified

⬡ Apollo: client defines a dataIdFromObject function that will be executed on every node

⬡ Fun fact: Relay stores each object it fetched in a key-value store with the object id or traverse path as key, any field that contains an object will actually be the key of the object, so two objects having the same id will be ensured the same by Implementation

Caching the query result

Page 67: Overview of GraphQL & Clients

Pagination

Page 68: Overview of GraphQL & Clients

Cursor Based Pagination

Page 69: Overview of GraphQL & Clients

⬢ Offset based pagination, e.g.: per_page=5&page=1

Cursor?

page 1 page 2 page 3

Page 70: Overview of GraphQL & Clients

⬢ Offset based pagination, e.g.: per_page=5&page=1

Cursor?

page 1 page 2 page 3

1 2 3 4 5

page 1

Client fetches page 1

Page 71: Overview of GraphQL & Clients

⬢ Offset based pagination, e.g.: per_page=5&page=1

Cursor?

page 1 page 2 page 3

' Broken

page 1 page 2 page 3

1 2 3 4 5

page 1

Data inserted

Page 72: Overview of GraphQL & Clients

⬢ Offset based pagination, e.g.: per_page=5&page=1

Cursor?

page 1 page 2 page 3

' Broken

page 1 page 2 page 3

1 2 3 4 5

page 1 page 2

5 6 7 8 9

'

Client got malformed results

Page 73: Overview of GraphQL & Clients

⬢ Offset based pagination, e.g.: per_page=5&page=1

⬢ Cursor based pagination, e.g.: after: "…", next: 5

Cursor?

next 5next 5

page 1 page 2 page 3

' Broken

page 1 page 2 page 3

Page 74: Overview of GraphQL & Clients

Relay Connections⬢ The design of Relay Cursor Connections

query { viewer { friends(first: 10, after: "someCursor") { edges { cursor node { id name } } pageInfo { hasNextPage } } } }

Edge (UserEdgeType)

Node (UserType)

{ … }

Cursor

Current cursor Connection

Edges

Edge (UserEdgeType)

Node (UserType)

{ … }

Cursor

Edge (UserEdgeType)

Node (UserType)

{ … }

Cursor

Page Info

Starting cursor

Page 75: Overview of GraphQL & Clients

Update

Page 76: Overview of GraphQL & Clients

Mutations⬢ A mutation is a query that has side effects

⬢ The changes made on the graph will be put on the response, the client is responsible to select the necessary parts

mutation { renameRepo(input: { repoID: "…", name: "NewName" }) { repo { id name } } }

Grab the changes that are

made on the existing repo

Page 77: Overview of GraphQL & Clients

Mutations⬢ A mutation is a query that has side effects

⬢ The changes made on the graph will be put on the response, the client is responsible to select the necessary parts

⬢ In general, we need to write an updater function to update the store with the payload:

(oldState, payload) => newState ⬢ Relay and Apollo both has some conventions

⬡ Objects with matching identifier in the store will be updated automatically

Page 78: Overview of GraphQL & Clients

Mutations

UI

$ㄎㄎㄎㄎ

dddddd

MutationStore

Page 79: Overview of GraphQL & Clients

Mutations

UI

$ㄎㄎㄎㄎ

dddddd

Mutation

Server

Store

Page 80: Overview of GraphQL & Clients

Mutations

UI

$ㄎㄎㄎㄎ

dddddd

Mutation

Server

Updater

Store

Response

Page 81: Overview of GraphQL & Clients

Mutations

UI

$ㄎㄎㄎㄎ

dddddd

Mutation

Server

Updater

Store

Response

Page 82: Overview of GraphQL & Clients

Optimistic Update

Page 83: Overview of GraphQL & Clients

Mutations

UI

$ㄎㄎㄎㄎ

dddddd

Mutation

Server

Updater

Store

Latency

Response

'

Page 84: Overview of GraphQL & Clients

Optimistic Update

UI

$ㄎㄎㄎㄎ

dddddd

MutationStore

Latency

Page 85: Overview of GraphQL & Clients

Optimistic Update

UI

$ㄎㄎㄎㄎ

dddddd

Mutation Optimistic Updater

Store

Latency

Optimistic Update Layer

Page 86: Overview of GraphQL & Clients

Optimistic Update

UI

$ㄎㄎㄎㄎ

dddddd

Mutation Optimistic Updater

Server

Updater

Store

Latency

Response

Optimistic Update Layer

Page 87: Overview of GraphQL & Clients

Optimistic Update

UI

$ㄎㄎㄎㄎ

dddddd

Mutation Optimistic Updater

Server

Updater

Store

Latency

Response

Page 88: Overview of GraphQL & Clients

Realtime UI

Page 89: Overview of GraphQL & Clients

GraphQL Live Query⬢ Idea: after the client sends a query, server can push

updates of the query result to the client

⬢ May require a fully reactive backend

⬢ No open implementations yet

Page 90: Overview of GraphQL & Clients

GraphQL Subscriptions⬢ Clients can subscribe to a specific type of event as a

similar way as how we do mutations ⬢ Mutations are client-made changes while

Subscriptions are server-pushed updates ⬢ New query results will be pushed to the client when a

event occurred

subscription { todoItemAddedToList(todoListID: "…") { todoItem { name } } }

Page 91: Overview of GraphQL & Clients

GraphQL Subscriptions⬢ Clients can subscribe to a specific type of event as a

similar way as how we do mutations ⬢ Mutations are client-made changes while

Subscriptions are server-pushed updates ⬢ New query results will be pushed to the client when a

event occurred ⬢ GraphQL just tells us how things should work, we

need to configure different implementations (WebSocket, APNS, GCM) of sending the data on different platforms

Page 92: Overview of GraphQL & Clients

GraphQL Subscriptions

UI

$ㄎㄎㄎㄎ

dddddd

Subscription

Server

Updater

Store

When event occurred

On mount (normally)

Page 93: Overview of GraphQL & Clients

References⬢ GraphQL API Explorer

⬢ GraphQL Concepts Visualized

⬢ Mutations and Optimistic UI in Apollo Client

⬢ GraphQL Subscriptions in Apollo Client

⬢ https://github.com/zetavg/graphql-todomvc

Page 94: Overview of GraphQL & Clients

Thanks + Q&A