Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
From REST to GraphQL
Marc-Andre Giroux
September 06, 2016
Programming
9
1.1k
From REST to GraphQL
Marc-Andre Giroux
September 06, 2016
Tweet
Share
More Decks by Marc-Andre Giroux
See All by Marc-Andre Giroux
It Depends - Examining GraphQL Myths & Assumptions
xuorig
0
60
So you Want to Distribute your GraphQL Schema?
xuorig
4
650
So you Want to Distribute your GraphQL Schema?
xuorig
0
330
GraphQL Schema Design @ Scale
xuorig
5
1.9k
Continuous Evolution of GraphQL Schemas @ GitHub
xuorig
3
1.6k
GraphQL à Shopify
xuorig
0
180
Exploring GraphQL
xuorig
0
230
GraphQL @ Shopify
xuorig
6
1.2k
GraphQL on Rails
xuorig
2
300
Other Decks in Programming
See All in Programming
How GitHub Supports Vim License Detection, The Five Years Journey
othree
1
390
Isar勉強会
hoddy3190
0
600
アジャイルで始める データ分析基盤構築
nagano
1
930
MLOps勉強会_リアルタイムトラフィックのサーバレスMLOps基盤_20220810
strsaito
1
460
Atomic Design とテストの○○な話
takfjp
2
830
Google IO 2022 社内LT会 / What's new in Android development tools
shingo_kobayashi
1
430
ExplainableAIの概要とAmazon SageMaker Clarifyでの実装例
hacarus
0
110
Amazon Lookout for Visionで 筆跡鑑定してみた
cmnakamurashogo
0
180
FargateとAthenaで作る、機械学習システム
nayuts
0
190
Rust、何もわからない...#3
estie
0
170
リーダブルテストコード / #vstat
jnchito
48
37k
테라폼으로 ECR 관리하기 (How to Manage ECR with Terraform)
posquit0
0
530
Featured
See All Featured
Web Components: a chance to create the future
zenorocha
303
40k
jQuery: Nuts, Bolts and Bling
dougneiner
56
6.4k
Infographics Made Easy
chrislema
233
17k
The Invisible Side of Design
smashingmag
290
48k
Fireside Chat
paigeccino
13
1.4k
GraphQLとの向き合い方2022年版
quramy
16
8.5k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
151
13k
The MySQL Ecosystem @ GitHub 2015
samlambert
239
11k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_i
25
15k
Bootstrapping a Software Product
garrettdimon
296
110k
How STYLIGHT went responsive
nonsquared
85
4k
Put a Button on it: Removing Barriers to Going Fast.
kastner
56
2.3k
Transcript
From REST to GraphQL Marc-Andre Giroux @__xuorig__
About me
None
A simple UI component
None
What kind of data is needed?
Cart Product ProductImage
Reusable endpoints (REST)
/carts/1 /products/1 /products/2 /products/3 /product_images/1 /product_images/2 /product_images/3
Too many round trips!
/carts/1?expand=products
/carts/1?fields=products(name, description, price)
/carts/1?fields=products/name,description,price
Custom Endpoints
/cart_with_all_the_stuff_i_need
None
/cart_with_all_the_stuff_i_need /cart_version_2_with_all_the_things /cart_with_products_and_images /cart_with_products_and_images_with_price_and_taxes my_tightly_coupled_custom_endpoint_including_only_the_things_i_need_bla_bla_bla_bla /cart_with_products_and_images_with_price_and_taxes_but_no_description /cart_with_products_and_images_with_price_and_taxes_but_no_description_v2
None
Server Client Updates a view Creates a new view Product
view v2 Product model changes Update endpoints Create new endpoint
GraphQL
What GraphQL is NOT
What GraphQL IS
{ myShop { name } } Field Selection Set
{ myShop { name } } Lexed Parsed Validated Executed
{ “myShop” { “name”: “GitHub” } }
{ myShop { name } }
{ myShop { name } }
None
{ shop(id: 1) { name } }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
{ “myShop”: { “name”: “Full Stack Fest Shop” “location” {
“city”: “Barcelona” “address”: “Av. Diagonal 547” } “products”: [{ “name”: “Conference Ticket” “price”: 500000 }, { “name”: “Cool T-Shirt” “price”: 20000 }] } }
Type System
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type QueryRoot { myShop: Shop shop(id: Int): Shop }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type Shop { name: String location: Address products(orderby: OrderEnum): [Product]
} enum ProductOrderEnum { PRICE, POPULARITY, ALPHABETICAL }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type Address { city: String address: String }
{ myShop { name location { city address } products(orderby:
POPULARITY) { name price } } }
type Product { name: String price: Int }
Fragments
{ myShop { name location { city address } products(orderby:
POPULARITY) { id name price } } }
None
{ myShop { name location { city address } products(orderby:
POPULARITY) { id name price } } }
fragment productFields on Product { id name price }
{ myShop { name location { city address } products(orderby:
POPULARITY) { ...productFields } } }
query Fragment Fragment Fragment Fragment
Introspection
query { __schema { … } }
Static Validation Code Generation IDE Integration Auto Documentation
None
None
Resolving fields
type Product { name: String price: Int }
ProductType = GraphQL::ObjectType.define do name "Product" description “A product sold
at a shop” # … end
field :name do type types.String resolve -> (obj, args, ctx)
{ obj.name } end
field :price do type types.Int resolve -> (obj, args, ctx)
do obj.subtotal + obj.taxes + obj.shipping_price end end
field :price do type types.Int resolve -> (obj, args, ctx)
do obj.subtotal + obj.taxes + obj.shipping_price end end
POST /graphql
Mutations
mutation { createProduct(name: “Nice Mug”, price: 10000) { id name
} }
Drawbacks and solutions
N+1 Queries
field :image do type ImageType resolve -> (product, args, ctx)
do product.image end end field :products do type [ProductType] resolve -> (shop, args, ctx) do shop.products end end
Product Load (1.0ms) SELECT "products".* FROM "products" WHERE "products"."shop_id" =
… Image Load (0.9ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = … Image Load (0.2ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = … Image Load (0.1ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = …
Solution: Batching + Caching
field :image do type ImageType resolve -> (product, args, ctx)
do RecordLoader.for(Image).load(product.image_id) end end
HTTP Caching
Solution: Client Side Cache
Normalized Cache
Normalized Cache
query { shop { products { price } } }
query { shop { product(id: 1) { price } } }
{ root: { shop: { products: [ Link.new(1) ] }
}, 1: { price: 1000 } }
https://github.com/facebook/relay http://www.apollostack.com/
Security
Query Depth Timeouts Query Complexity
Future
Subscriptions
subscription { productInventorySubscribe { products { inventory } } }
Deferred Queries
query { shop { name description products { name price
} } }
query { shop { name description products { name price
} } }
query { shop { name description products @defer { name
price } } }
None
None
Thank you Marc-Andre Giroux @__xuorig__