SlideShare a Scribd company logo
1 of 94
Download to read offline
Overview of

GraphQL & Clients
! # @zetavg

fb.me/pokaichang72
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
! # @zetavg

fb.me/pokaichang72
⬡ Complain about RESTful Introduce GraphQL
⬡ Just enough GraphQL to get started
⬡ GraphQL client library overview
⬡ Intro to Relay
⬡ Demo: GraphQL & Relay on Rails

https://github.com/zetavg/RailsRelayTodoMVC
Outline
Background of API
Developing
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
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
/api/v1/posts.json
/api/v2/posts.json
/api/v3/posts.json
/api/v4/posts.json
/api/v65535/posts.json
⋯⋯
/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_
API should be like this
Not this
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 )
A Glance on GraphQL
All your application data 

can be represented as a graph
$
{
"name": "Pokai Chang",
"bio":"Yet another geek.",
"followers": [◌, ◌, ◌],
"repos": [◌, ◌, ◌]

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

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

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

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

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

}
!
{ }
{
"viewer": ◌

}
A subset of the graph 

is used to show an UI
$
{
}
$
{
"name": "Pusheen",
"bio":"Nyan nyan nyan~",
"followers": [◌],
"repos": [◌]

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

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

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

}
!
{
"name": "Thing Compile
"description": "...",
"stargazers": [◌, ◌, ◌
}
!
{
"name"
"descr
"starg
}
{ }
{
"viewer": ◌

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

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

}
!
{
"name": "Thing Compile
"description": "...",
"stargazers": [◌, ◌, ◌
}
!
{
"name"
"descr
"starg
}
!
{
"n
"d
"s
}
!
{
"name": "Todo",
"description": "...",
"stargazers": [◌]

}
{ }
{
"viewer": ◌

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

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

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

}
$
$
$
$
$
$
!
{
"name"
"descr
"starg
}
!
{
"name": "Thing Compile
"description": "...",
"stargazers": [◌, ◌, ◌
}
$
{
"name": "Pusheen",
"bio":"Nyan nyan nyan~",
"followers": [◌],
"repos": [◌]

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

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

}
{ }
{
"viewer": ◌

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

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

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

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

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

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

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

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

}
!
{ }
{
"viewer": ◌

}
GraphQL
⬡ Complain about RESTful Introduce GraphQL
⬡ Just enough GraphQL to get started
⬡ GraphQL client library overview
⬡ Intro to Relay
⬡ Demo: GraphQL & Relay on Rails

https://github.com/zetavg/RailsRelayTodoMVC
Outline
Basic Query
⬢ Starts with selecting fields on the query root
⬢ WYSIWYG
{
"data": {
"viewer": {
"name": "Pokai Chang"
}
}
}
query {
viewer {
name
}
}
Basic Query
⬢ Querying nested fields
{
"data": {
"viewer": {
"name": "Pokai Chang",
"birthday": {
"month": 7,
"day": 2
}
}
}
}
query {
viewer {
name
birthday {
month
day
}
}
}
Types
⬢ Get the type of a object using the __typename
meta field
{
"data": {
"viewer": {
"__typename": "User",
"birthday": {
"__typename": "Date"
}
}
}
}
query {
viewer {
__typename
birthday {
__typename
}
}
}
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
}
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
Arguments
⬢ Arguments can be defined on fields
query {
user(id: 1) {
name
}
}
Arguments
⬢ Nested fields also can have arguments
query {
user(id: 1) {
name
repo(name: "awesome-graphql") {
name
description
}
}
}
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"
}
+
Fragment
fragment profileFields on User {
name
bio
avatarUrl
}
query {
viewer {
...profileFields
}
user(id: 1) {
...profileFields
}
}
Pre-define a set of fields

on a type or interface
as meaningful fragment
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!
# Sample Query
fragment actorFields on Actor {
name
bio
avatarUrl
}
query {
feed {
actor {
...actorFields
}

verb

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
}
}
}
}
Input Types
⬢ Yes, inputs are also typed
input AddCommentInput {
subjectId: ID!
body: String!
}
mutation {
addComment(input: { subjectId: 1, body: "Hi." }) {
subject {
comments {
body
}
}
}
}
GraphiQL
⬢ An open source GraphQL playground
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
}
}
}
$
{
"name": "J
"bio":"...
"followers
"repos": [
}
$
{
"name": "Pusheen",
"bio":"Nyan nyan nyan~",
"followers": [◌],
$
{
"name": "Lucy",
"bio":"...",
"followers": [◌],
"repos": [◌, ◌]

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

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

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

}
!
{
"name": "Handy Ut
"description": ".
"stargazers": [◌]
{ }
{
"viewer": ◌

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

}
Query tree
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": [◌, ◌, ◌]

}
graphql.org
⬡ Complain about RESTful Introduce GraphQL
⬡ Just enough GraphQL to get started
⬡ GraphQL client library overview
⬡ Intro to Relay
⬡ Demo: GraphQL & Relay on Rails

https://github.com/zetavg/RailsRelayTodoMVC
Outline
Fetching
Pagination

Caching
Update
Optimistic Update
Realtime UI
Fetching
const View = (data) => UI
Redux data flow
View
State
subscribe
Redux Store
Redux data flow
View
State
Reducer
Action
subscribe
prevState
Redux data flow
View
State
Reducer
Action
subscribe
prevState
Backend ?
Redux data flow
View
State
Reducer
Action
subscribe
prevState
Backend
Action
Action
Action
$
{
"name": "Neson",
"bio":"Yet another geek.",
"followers": [◌, ◌, ◌],
"repos": [◌, ◌, ◌]

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

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

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

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

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

}
!
{ }
{
"viewer": ◌

}
GraphQL
Relay data fetching
View
$
$
$ $
$
dd
$ $ $ $
dd
dd
dd
Relay Store
Relay data fetching
viewer {
name
bio
}
View
dd
dd
dd
dd
viewer {
repos {
name
description
}
}
$
Relay Store
Relay data fetching
View
dd
dd
dd
dd
viewer {
repos {
name
description
}
}
Backend
query {
viewer {

name

bio
repos {
name
description
}
}
}
$
Relay Store
viewer {
name
bio
}
Relay data fetching
View
dd
dd
dd
dd
viewer {
repos {
name
description
}
}
Backend
{
"data": {
"viewer": {

"name": "…",
"bio": "…",
"followers": […],
"repos": […]
}
}
}
$
viewer {
name
bio
}
query {
viewer {

name

bio
repos {
name
description
}
}
}
Relay data fetching
View
$
ㄎㄎㄎㄎ
viewer {
repos {
name
description
}
}
dd
dd
dd
dd
viewer {
name
bio
}
View
Relay data fetching
viewer {
name
bio
}
View
$
ㄎㄎㄎㄎ
viewer {
following {
name
}
}
dd
dd
dd
dd
$
$
$
$
$
View
Relay data fetching
viewer {
name
bio
}
View
$
ㄎㄎㄎㄎ
viewer {
following {
name
}
}
dd
dd
dd
dd
$
$
$
$
$
Backend
query {
viewer {
following {
name
}
}
}
{
"data": {
"viewer": {
"following": […]
}
}
}
View
Relay data fetching
viewer {
name
bio
}
View
$
ㄎㄎㄎㄎ
viewer {
following {
name
}
}
dd
dd
dd
dd
$
$
$
$
$
ㄎㄎㄎㄎ
Caching
Query tree
query {
user(login: "zetavg") {
name
repositories {
name
}
}
}
{
"data": {
"user": {
"name": "Pokai Chang",
"repositories": [
{ "name": "dotfiles" },
{ "name": "Thing" },
{ "name": "Stuff" }
]
}
}
}
Query tree
Query 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" }
]
}
}
}
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
⬢ 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
⬢ 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
⬢ 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
⬢ 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
⬢ 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
⬢ 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
Pagination
Cursor Based Pagination
⬢ Offset based pagination, e.g.: per_page=5&page=1
Cursor?
page 1 page 2 page 3
⬢ 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
⬢ 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
⬢ 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
⬢ 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
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 (UserEdgeTy
Node (UserType
{ … }
Cursor
Page Info
Starting cursor
Update
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
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
Mutations
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation
Store
Mutations
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation
Server
Store
Mutations
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation
Server
Updater
Store
Response
Mutations
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation
Server
Updater
Store
Response
Optimistic Update
Mutations
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation
Server
Updater
Store
Latency
Response
'
Optimistic Update
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation
Store
Latency
Optimistic Update
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation Optimistic Updater
Store
Latency
Optimistic Update
Layer
Optimistic Update
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation Optimistic Updater
Server
Updater
Store
Latency
Response
Optimistic Update
Layer
Optimistic Update
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Mutation Optimistic Updater
Server
Updater
Store
Latency
Response
Realtime UI
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
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
}
}
}
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
GraphQL Subscriptions
UI
$
ㄎㄎㄎㄎ
dd
dd
dd
Subscription
Server
Updater
Store
When event occurred
On mount (normally)
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
Thanks + Q&A

More Related Content

What's hot

Pragmatic REST APIs
Pragmatic REST APIsPragmatic REST APIs
Pragmatic REST APIsamesar0
 
The Future is Federated
The Future is FederatedThe Future is Federated
The Future is FederatedRuben Verborgh
 
Creating 3rd Generation Web APIs with Hydra
Creating 3rd Generation Web APIs with HydraCreating 3rd Generation Web APIs with Hydra
Creating 3rd Generation Web APIs with HydraMarkus Lanthaler
 
JSON-LD update DC 2017
JSON-LD update DC 2017JSON-LD update DC 2017
JSON-LD update DC 2017Gregg Kellogg
 
Elasticsearch in 15 minutes
Elasticsearch in 15 minutesElasticsearch in 15 minutes
Elasticsearch in 15 minutesDavid Pilato
 
Building Next-Generation Web APIs with JSON-LD and Hydra
Building Next-Generation Web APIs with JSON-LD and HydraBuilding Next-Generation Web APIs with JSON-LD and Hydra
Building Next-Generation Web APIs with JSON-LD and HydraMarkus Lanthaler
 
Integrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software CloudIntegrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software CloudAtlassian
 
Distributed percolator in elasticsearch
Distributed percolator in elasticsearchDistributed percolator in elasticsearch
Distributed percolator in elasticsearchmartijnvg
 
The Digital Cavemen of Linked Lascaux
The Digital Cavemen of Linked LascauxThe Digital Cavemen of Linked Lascaux
The Digital Cavemen of Linked LascauxRuben Verborgh
 
Open Standards for the Semantic Web: XML / RDF(S) / OWL / SOAP
Open Standards for the Semantic Web: XML / RDF(S) / OWL / SOAPOpen Standards for the Semantic Web: XML / RDF(S) / OWL / SOAP
Open Standards for the Semantic Web: XML / RDF(S) / OWL / SOAPPieter De Leenheer
 
Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responsesdarrelmiller71
 
Ontotext's GraphDB Connectors
Ontotext's GraphDB ConnectorsOntotext's GraphDB Connectors
Ontotext's GraphDB Connectorslogomachy
 
Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]
Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]
Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]Otávio Santana
 
Initial Usage Analysis of DBpedia's Triple Pattern Fragments
Initial Usage Analysis of DBpedia's Triple Pattern FragmentsInitial Usage Analysis of DBpedia's Triple Pattern Fragments
Initial Usage Analysis of DBpedia's Triple Pattern FragmentsRuben Verborgh
 
Tabular Data on the Web
Tabular Data on the WebTabular Data on the Web
Tabular Data on the WebGregg Kellogg
 
Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]
Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]
Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]Otávio Santana
 
Harnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, Germany
Harnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, GermanyHarnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, Germany
Harnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, GermanyAndré Ricardo Barreto de Oliveira
 
Elasticsearch first-steps
Elasticsearch first-stepsElasticsearch first-steps
Elasticsearch first-stepsMatteo Moci
 

What's hot (20)

Pragmatic REST APIs
Pragmatic REST APIsPragmatic REST APIs
Pragmatic REST APIs
 
The Future is Federated
The Future is FederatedThe Future is Federated
The Future is Federated
 
Creating 3rd Generation Web APIs with Hydra
Creating 3rd Generation Web APIs with HydraCreating 3rd Generation Web APIs with Hydra
Creating 3rd Generation Web APIs with Hydra
 
JSON-LD update DC 2017
JSON-LD update DC 2017JSON-LD update DC 2017
JSON-LD update DC 2017
 
BigML.io - The BigML API
BigML.io - The BigML APIBigML.io - The BigML API
BigML.io - The BigML API
 
Elasticsearch in 15 minutes
Elasticsearch in 15 minutesElasticsearch in 15 minutes
Elasticsearch in 15 minutes
 
Building Next-Generation Web APIs with JSON-LD and Hydra
Building Next-Generation Web APIs with JSON-LD and HydraBuilding Next-Generation Web APIs with JSON-LD and Hydra
Building Next-Generation Web APIs with JSON-LD and Hydra
 
Integrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software CloudIntegrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software Cloud
 
Distributed percolator in elasticsearch
Distributed percolator in elasticsearchDistributed percolator in elasticsearch
Distributed percolator in elasticsearch
 
The Digital Cavemen of Linked Lascaux
The Digital Cavemen of Linked LascauxThe Digital Cavemen of Linked Lascaux
The Digital Cavemen of Linked Lascaux
 
Open Standards for the Semantic Web: XML / RDF(S) / OWL / SOAP
Open Standards for the Semantic Web: XML / RDF(S) / OWL / SOAPOpen Standards for the Semantic Web: XML / RDF(S) / OWL / SOAP
Open Standards for the Semantic Web: XML / RDF(S) / OWL / SOAP
 
Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responses
 
Ontotext's GraphDB Connectors
Ontotext's GraphDB ConnectorsOntotext's GraphDB Connectors
Ontotext's GraphDB Connectors
 
Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]
Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]
Eclipse JNoSQL: One API to Many NoSQL Databases - BYOL [HOL5998]
 
Initial Usage Analysis of DBpedia's Triple Pattern Fragments
Initial Usage Analysis of DBpedia's Triple Pattern FragmentsInitial Usage Analysis of DBpedia's Triple Pattern Fragments
Initial Usage Analysis of DBpedia's Triple Pattern Fragments
 
Tabular Data on the Web
Tabular Data on the WebTabular Data on the Web
Tabular Data on the Web
 
Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]
Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]
Jakarta EE Meets NoSQL in the Cloud Age [DEV6109]
 
Harnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, Germany
Harnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, GermanyHarnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, Germany
Harnessing The Power of Search - Liferay DEVCON 2015, Darmstadt, Germany
 
Elasticsearch first-steps
Elasticsearch first-stepsElasticsearch first-steps
Elasticsearch first-steps
 
Advanced Json
Advanced JsonAdvanced Json
Advanced Json
 

Similar to GraphQL & Clients Overview

Better APIs with GraphQL
Better APIs with GraphQL Better APIs with GraphQL
Better APIs with GraphQL Josh Price
 
Next-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNext-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNikolas Burk
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedMarcinStachniuk
 
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScriptMongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScriptMongoDB
 
Data models in Angular 1 & 2
Data models in Angular 1 & 2Data models in Angular 1 & 2
Data models in Angular 1 & 2Adam Klein
 
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017Codemotion
 
Nikita Galkin "Looking for the right tech stack for GraphQL application"
Nikita Galkin "Looking for the right tech stack for GraphQL application"Nikita Galkin "Looking for the right tech stack for GraphQL application"
Nikita Galkin "Looking for the right tech stack for GraphQL application"Fwdays
 
Getting Started with GraphQL && PHP
Getting Started with GraphQL && PHPGetting Started with GraphQL && PHP
Getting Started with GraphQL && PHPAndrew Rota
 
GraphQL in Symfony
GraphQL in SymfonyGraphQL in Symfony
GraphQL in SymfonyBernd Alter
 
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB
 
GraphQL in an Age of REST
GraphQL in an Age of RESTGraphQL in an Age of REST
GraphQL in an Age of RESTYos Riady
 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchNikolas Burk
 
Managing GraphQL servers with AWS Fargate & Prisma Cloud
Managing GraphQL servers  with AWS Fargate & Prisma CloudManaging GraphQL servers  with AWS Fargate & Prisma Cloud
Managing GraphQL servers with AWS Fargate & Prisma CloudNikolas Burk
 
Building Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreBuilding Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreStormpath
 
Introduction to Grails Framework
Introduction to Grails FrameworkIntroduction to Grails Framework
Introduction to Grails FrameworkPT.JUG
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedMarcinStachniuk
 
Building a GraphQL API in PHP
Building a GraphQL API in PHPBuilding a GraphQL API in PHP
Building a GraphQL API in PHPAndrew Rota
 
20170624 GraphQL Presentation
20170624 GraphQL Presentation20170624 GraphQL Presentation
20170624 GraphQL PresentationMartin Heidegger
 

Similar to GraphQL & Clients Overview (20)

Better APIs with GraphQL
Better APIs with GraphQL Better APIs with GraphQL
Better APIs with GraphQL
 
Next-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNext-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and Prisma
 
GraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learnedGraphQL - when REST API is not enough - lessons learned
GraphQL - when REST API is not enough - lessons learned
 
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScriptMongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
MongoDB World 2019: Building a GraphQL API with MongoDB, Prisma, & TypeScript
 
Data models in Angular 1 & 2
Data models in Angular 1 & 2Data models in Angular 1 & 2
Data models in Angular 1 & 2
 
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
Tomer Elmalem - GraphQL APIs: REST in Peace - Codemotion Milan 2017
 
Nikita Galkin "Looking for the right tech stack for GraphQL application"
Nikita Galkin "Looking for the right tech stack for GraphQL application"Nikita Galkin "Looking for the right tech stack for GraphQL application"
Nikita Galkin "Looking for the right tech stack for GraphQL application"
 
Getting Started with GraphQL && PHP
Getting Started with GraphQL && PHPGetting Started with GraphQL && PHP
Getting Started with GraphQL && PHP
 
GraphQL in Symfony
GraphQL in SymfonyGraphQL in Symfony
GraphQL in Symfony
 
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and TypescriptMongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
MongoDB.local Berlin: Building a GraphQL API with MongoDB, Prisma and Typescript
 
GraphQL in an Age of REST
GraphQL in an Age of RESTGraphQL in an Age of REST
GraphQL in an Age of REST
 
HyperGraphQL
HyperGraphQLHyperGraphQL
HyperGraphQL
 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from Scratch
 
Managing GraphQL servers with AWS Fargate & Prisma Cloud
Managing GraphQL servers  with AWS Fargate & Prisma CloudManaging GraphQL servers  with AWS Fargate & Prisma Cloud
Managing GraphQL servers with AWS Fargate & Prisma Cloud
 
Building Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreBuilding Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET Core
 
React & GraphQL
React & GraphQLReact & GraphQL
React & GraphQL
 
Introduction to Grails Framework
Introduction to Grails FrameworkIntroduction to Grails Framework
Introduction to Grails Framework
 
GraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learnedGraphQL - when REST API is to less - lessons learned
GraphQL - when REST API is to less - lessons learned
 
Building a GraphQL API in PHP
Building a GraphQL API in PHPBuilding a GraphQL API in PHP
Building a GraphQL API in PHP
 
20170624 GraphQL Presentation
20170624 GraphQL Presentation20170624 GraphQL Presentation
20170624 GraphQL Presentation
 

More from Pokai Chang

Colorgy - 校園 Open API 平台
Colorgy - 校園 Open API 平台Colorgy - 校園 Open API 平台
Colorgy - 校園 Open API 平台Pokai Chang
 
Git 實務圖解
Git 實務圖解Git 實務圖解
Git 實務圖解Pokai Chang
 
Intensive Wireless Communications Engineering: Current Practices (Instructor ...
Intensive Wireless Communications Engineering: Current Practices (Instructor ...Intensive Wireless Communications Engineering: Current Practices (Instructor ...
Intensive Wireless Communications Engineering: Current Practices (Instructor ...Pokai Chang
 
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理Pokai Chang
 
WCET 認證與培訓計畫說明 by 鄭瑞光教授
WCET 認證與培訓計畫說明 by 鄭瑞光教授WCET 認證與培訓計畫說明 by 鄭瑞光教授
WCET 認證與培訓計畫說明 by 鄭瑞光教授Pokai Chang
 
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理Pokai Chang
 

More from Pokai Chang (6)

Colorgy - 校園 Open API 平台
Colorgy - 校園 Open API 平台Colorgy - 校園 Open API 平台
Colorgy - 校園 Open API 平台
 
Git 實務圖解
Git 實務圖解Git 實務圖解
Git 實務圖解
 
Intensive Wireless Communications Engineering: Current Practices (Instructor ...
Intensive Wireless Communications Engineering: Current Practices (Instructor ...Intensive Wireless Communications Engineering: Current Practices (Instructor ...
Intensive Wireless Communications Engineering: Current Practices (Instructor ...
 
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
 
WCET 認證與培訓計畫說明 by 鄭瑞光教授
WCET 認證與培訓計畫說明 by 鄭瑞光教授WCET 認證與培訓計畫說明 by 鄭瑞光教授
WCET 認證與培訓計畫說明 by 鄭瑞光教授
 
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
無線通訊產業之發展趨勢與人才需求 by 經濟部通訊產業發展推動小組 黃建智 經理
 

Recently uploaded

React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...Karmanjay Verma
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentMahmoud Rabie
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Karmanjay Verma
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...amber724300
 
WomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyoneWomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyoneUiPathCommunity
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxAna-Maria Mihalceanu
 

Recently uploaded (20)

React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career Development
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
 
WomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyoneWomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyone
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance Toolbox
 

GraphQL & Clients Overview

  • 1. Overview of
 GraphQL & Clients ! # @zetavg
 fb.me/pokaichang72
  • 2. 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 ! # @zetavg
 fb.me/pokaichang72
  • 3. ⬡ Complain about RESTful Introduce GraphQL ⬡ Just enough GraphQL to get started ⬡ GraphQL client library overview ⬡ Intro to Relay ⬡ Demo: GraphQL & Relay on Rails
 https://github.com/zetavg/RailsRelayTodoMVC Outline
  • 5. 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
  • 6. 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
  • 9. API should be like this
  • 11. 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 )
  • 12. A Glance on GraphQL
  • 13. All your application data 
 can be represented as a graph
  • 14. $ { "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌]
 } $ { "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌]
 } $ { "name": "Ja "bio":"..." "followers" "repos": [◌ } $ { "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌]
 } ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } ! { "name": "Hello World", "description": "...", "stargazers": [◌, ◌]
 } ! { "name": "Handy Ut "description": ". "stargazers": [◌] } ! { "name": "Awes "description" "stargazers": } ! { "name": "Todo", "description": "...", "stargazers": [◌]
 } ! { } { "viewer": ◌
 }
  • 15. A subset of the graph 
 is used to show an UI
  • 16. $ { } $ { "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌]
 } $ { "name": "Lucy", "bio":"...", "followers": [◌] "repos": [◌, ◌]
 } ! { "n "d "s } ! { "name": "Todo", "description": "...", "stargazers": [◌]
 } ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } ! { "name": "Thing Compile "description": "...", "stargazers": [◌, ◌, ◌ } ! { "name" "descr "starg } { } { "viewer": ◌
 } $ { "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌]
 } $ dd dd dd dd
  • 17. ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } ! { "name": "Thing Compile "description": "...", "stargazers": [◌, ◌, ◌ } ! { "name" "descr "starg } ! { "n "d "s } ! { "name": "Todo", "description": "...", "stargazers": [◌]
 } { } { "viewer": ◌
 } $ { "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌]
 } $ { "name": "Lucy", "bio":"...", "followers": [◌] "repos": [◌, ◌]
 } $ { } $ { "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌]
 } $ $ $ $ $ $
  • 18. ! { "name" "descr "starg } ! { "name": "Thing Compile "description": "...", "stargazers": [◌, ◌, ◌ } $ { "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌]
 } ! { "n "d "s } ! { "name": "Todo", "description": "...", "stargazers": [◌]
 } ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } { } { "viewer": ◌
 } $ $ $ $ $ $ $ $ $ $ $ / $ { "name": "Lucy", "bio":"...", "followers": [◌] "repos": [◌, ◌]
 } $ { } $ { "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌]
 }
  • 19. $ { "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌]
 } $ { "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌]
 } $ { "name": "Ja "bio":"..." "followers" "repos": [◌ } $ { "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌]
 } ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } ! { "name": "Hello World", "description": "...", "stargazers": [◌, ◌]
 } ! { "name": "Handy Ut "description": ". "stargazers": [◌] } ! { "name": "Awes "description" "stargazers": } ! { "name": "Todo", "description": "...", "stargazers": [◌]
 } ! { } { "viewer": ◌
 } GraphQL
  • 20. ⬡ Complain about RESTful Introduce GraphQL ⬡ Just enough GraphQL to get started ⬡ GraphQL client library overview ⬡ Intro to Relay ⬡ Demo: GraphQL & Relay on Rails
 https://github.com/zetavg/RailsRelayTodoMVC Outline
  • 21. Basic Query ⬢ Starts with selecting fields on the query root ⬢ WYSIWYG { "data": { "viewer": { "name": "Pokai Chang" } } } query { viewer { name } }
  • 22. Basic Query ⬢ Querying nested fields { "data": { "viewer": { "name": "Pokai Chang", "birthday": { "month": 7, "day": 2 } } } } query { viewer { name birthday { month day } } }
  • 23. Types ⬢ Get the type of a object using the __typename meta field { "data": { "viewer": { "__typename": "User", "birthday": { "__typename": "Date" } } } } query { viewer { __typename birthday { __typename } } }
  • 24. 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 }
  • 25. 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
  • 26. Arguments ⬢ Arguments can be defined on fields query { user(id: 1) { name } }
  • 27. Arguments ⬢ Nested fields also can have arguments query { user(id: 1) { name repo(name: "awesome-graphql") { name description } } }
  • 28. 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" } +
  • 29. Fragment fragment profileFields on User { name bio avatarUrl } query { viewer { ...profileFields } user(id: 1) { ...profileFields } } Pre-define a set of fields
 on a type or interface as meaningful fragment
  • 30. 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! # Sample Query fragment actorFields on Actor { name bio avatarUrl } query { feed { actor { ...actorFields }
 verb

  • 31. 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 } } } }
  • 32. Input Types ⬢ Yes, inputs are also typed input AddCommentInput { subjectId: ID! body: String! } mutation { addComment(input: { subjectId: 1, body: "Hi." }) { subject { comments { body } } } }
  • 33. GraphiQL ⬢ An open source GraphQL playground
  • 34. 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 } } }
  • 35. $ { "name": "J "bio":"... "followers "repos": [ } $ { "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], $ { "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌]
 } ! { "name": "Awe "description "stargazers" } ! { "name": "Todo", "description": "...", "stargazers": [◌]
 } ! ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } ! { "name": "Handy Ut "description": ". "stargazers": [◌] { } { "viewer": ◌
 } $ { "name": "Pokai Chang", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌]
 } Query tree
  • 36. 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": [◌, ◌, ◌]
 }
  • 38. ⬡ Complain about RESTful Introduce GraphQL ⬡ Just enough GraphQL to get started ⬡ GraphQL client library overview ⬡ Intro to Relay ⬡ Demo: GraphQL & Relay on Rails
 https://github.com/zetavg/RailsRelayTodoMVC Outline
  • 40.
  • 42.
  • 43. const View = (data) => UI
  • 48. $ { "name": "Neson", "bio":"Yet another geek.", "followers": [◌, ◌, ◌], "repos": [◌, ◌, ◌]
 } $ { "name": "Lucy", "bio":"...", "followers": [◌], "repos": [◌, ◌]
 } $ { "name": "Ja "bio":"..." "followers" "repos": [◌ } $ { "name": "Pusheen", "bio":"Nyan nyan nyan~", "followers": [◌], "repos": [◌]
 } ! { "name": "Thing Compiler", "description": "...", "stargazers": [◌, ◌, ◌]
 } ! { "name": "Hello World", "description": "...", "stargazers": [◌, ◌]
 } ! { "name": "Handy Ut "description": ". "stargazers": [◌] } ! { "name": "Awes "description" "stargazers": } ! { "name": "Todo", "description": "...", "stargazers": [◌]
 } ! { } { "viewer": ◌
 } GraphQL
  • 49. Relay data fetching View $ $ $ $ $ dd $ $ $ $ dd dd dd Relay Store
  • 50. Relay data fetching viewer { name bio } View dd dd dd dd viewer { repos { name description } } $ Relay Store
  • 51. Relay data fetching View dd dd dd dd viewer { repos { name description } } Backend query { viewer {
 name
 bio repos { name description } } } $ Relay Store viewer { name bio }
  • 52. Relay data fetching View dd dd dd dd viewer { repos { name description } } Backend { "data": { "viewer": {
 "name": "…", "bio": "…", "followers": […], "repos": […] } } } $ viewer { name bio } query { viewer {
 name
 bio repos { name description } } }
  • 53. Relay data fetching View $ ㄎㄎㄎㄎ viewer { repos { name description } } dd dd dd dd viewer { name bio }
  • 54. View Relay data fetching viewer { name bio } View $ ㄎㄎㄎㄎ viewer { following { name } } dd dd dd dd $ $ $ $ $
  • 55. View Relay data fetching viewer { name bio } View $ ㄎㄎㄎㄎ viewer { following { name } } dd dd dd dd $ $ $ $ $ Backend query { viewer { following { name } } } { "data": { "viewer": { "following": […] } } }
  • 56. View Relay data fetching viewer { name bio } View $ ㄎㄎㄎㄎ viewer { following { name } } dd dd dd dd $ $ $ $ $ ㄎㄎㄎㄎ
  • 58. Query tree query { user(login: "zetavg") { name repositories { name } } } { "data": { "user": { "name": "Pokai Chang", "repositories": [ { "name": "dotfiles" }, { "name": "Thing" }, { "name": "Stuff" } ] } } }
  • 59. Query tree Query 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" } ] } } }
  • 60. 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
  • 61. ⬢ 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
  • 62. ⬢ 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
  • 63. ⬢ 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
  • 64. ⬢ 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
  • 65. ⬢ 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
  • 66. ⬢ 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
  • 69. ⬢ Offset based pagination, e.g.: per_page=5&page=1 Cursor? page 1 page 2 page 3
  • 70. ⬢ 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
  • 71. ⬢ 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
  • 72. ⬢ 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
  • 73. ⬢ 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
  • 74. 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 (UserEdgeTy Node (UserType { … } Cursor Page Info Starting cursor
  • 76. 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
  • 77. 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
  • 85. Optimistic Update UI $ ㄎㄎㄎㄎ dd dd dd Mutation Optimistic Updater Store Latency Optimistic Update Layer
  • 86. Optimistic Update UI $ ㄎㄎㄎㄎ dd dd dd Mutation Optimistic Updater Server Updater Store Latency Response Optimistic Update Layer
  • 87. Optimistic Update UI $ ㄎㄎㄎㄎ dd dd dd Mutation Optimistic Updater Server Updater Store Latency Response
  • 89. 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
  • 90. 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 } } }
  • 91. 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
  • 93. 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