Zero to GraphQL in 30 Minutes – Steven Luscher

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everybody welcome to Facebook my name's Steve Buescher and I work on the relay team at at Facebook and this talk is called zero to graph QL in 30 minutes something that I hear time and time again from conference attendees and react developers is that they would love to get started and try all of the stuff that Greg just showed you they want to get started with graph QL but they know that in order to do so they're going to be able to have to vend their data through a graph QL endpoint and frankly making the investment in a graph QL endpoint atop their existing infrastructure is kind of a barrier to adoption right and I'm sure some of you feel this here so what I'd like to do today is I would like to do a demonstration of just how minimal an investment you can make to stand up a graph QL endpoint atop your existing infrastructure without having to rewrite any of your data layer whatsoever and I'm going to do so by sort of skimming off the top of you know the web frameworks du jour I'm going to try Jango for Python developers I'm going to try rails for Ruby developers and then we're going to do a JavaScript example in node 4 you know whatever kind of service-oriented architecture that you can think of so graph gel 0 de Graaff Gil in 30 minutes this is a time trial so we better get started all right so put yourself in the shoes of your average Python developer you're developing a large django app and maybe your django app does something like this it exposes a you know a person model and you have a people endpoint and this people endpoint ven's you some people I can say people slash 1 to get the person with with ID 1 and I have some properties on a person first name last name email username I also have an association to some other people through friendships here I have two friends now let's say that I was charged with building easier interface where I had to render a list of this person's friends with the first name and email of each one of the friends I do not have enough data here to be able to do that all I have is a URL where I can more information about friends 2 & 3 so the temptation might be to sort of twiddle with the URL and add like an include friend details you know email first name kind of thing right or maybe that there's the temptation to you know break off a new endpoint like people with friend details you know slash one or something like that some of you are chuckling because you know that as time goes on this can lead to an explosion of custom endpoints that we'd rather stay away from wouldn't it be awesome if instead we could create a query for a person with the ID one and if I could ask for some fields on it that I am interested in like a first name and a last name and an email address and a user name and if I could dive into their friends and pick only the first name and email from the friends wouldn't it be awesome if I could execute a query that looked like this and get a response that has exactly the same shape as the query that I just made with only the fields that I requested with no risk of over fetching data that I'm not going to use and no risk of under fetching for data that I definitely need to render in my user interface well as most of you can probably guess what you're looking at on screen is graph QL and I'm going to show you how to hey hey I didn't write it I'm going to show you how to stand up a graph QL endpoint in this django app right now alright so no cheating let's go all the way back get checkout master we're going to start from a blank slate first thing I'm going to do is I'm going to use the Python installer pip install and I'm going to install the excellent graphene library with the Django extensions I'm also going to install django graf thick kohl graphical is the graphical interface to browse a graph QL endpoint that you just saw in the browser alright so now with those things installed let's write some Python code so a schema that your job as a client dev is to export a schema that describes your data universe and I'm going to do it with graphene I'm going to import graphene and I'm going to export one of these schema things graphene is a set of helper methods that help me create a schema every grade scream s starts with a route field called query that's of query type so what's in a query type a query type is a subclass of an object type object type has a name an optional description and then it's going to have some fields let's just do the hello world for now let's say I want a field called hello and it's going to be of type string now I'm going to have to write a Python method that returns me this mythical string and I'm going to do it like so resolved hello it's going to take in a root some optional arguments and some info some context about the request this might be the logged in user or you know context about the HTTP requests and now on this line it's my job to do whatever I want anything that's available in Django Python so long as I return a string I'm going to cop out and I'm just going to return the string world alright let's see how we did I'm going to jump back into the browser I'm going to refresh her and say query now I have this hello field that's available and if I execute this query the response was the return value of that resolver world all right so here's what I really want what I really want is I want a person field and I want it to be a field of type person type and I want it to take an argument that's a string and I want this and now I'm going to have to do some work to resolve this so if I want to resolve a person from the root get some args and some optional info now I'm going to have to do some work that returns a person anyone who has worked with Jango will recognize the following API if I have a person model I can use this API object get to get a person by their primary ID and the ID I can pull right out of args like so from my people app the models import that person model and I should be good to go person is going to pull ID out of args and it's going to use the Django API to read it out of the database all right this is no good unless I tell it what a person type is so let's do it person type is also a subclass of the object type has a name and an optional description and some fields first field I want to create is the first name field which is a graphene string all right what do you think do I have enough here in terms of my schema description let's jump into the browser and check all right so on my query I now have a person field at the root which accepts an ID argument which I can pass the string 1 and on that person it looks like there's a first name field exposed and when I hit run it pulls that straight out of the database through the Django model you didn't change your data layer whatsoever and now you stood up a grant graph QL endpoint in a Django app let's keep going we have first name we have last name we have email user name and ID and then now we're going to have to deal with this Friends Association I want to create a friend's field which is fundamentally a list of stuff and it's a list of person types and in graphene I can just write self to refer to you know the present type now I'm going to need a little bit of help to resolve friends given that I start from a person at this node with some optional args and info that I don't need to use how am I going to return their friends again the Django Model API if I if I if I query person friends that gives me an association object that describes the association between a person and their friends and then if I call the all accessor that's going to turn it into a numerable list of friends that I can return through through the resolver so with any luck I now should be able to query all of these other fields like so and I should be able to dive into the Friends Association get a first name and an email execute this query and it goes straight through the Django Model Association for friends and it grabs the first name and email of my friends Adrian and Simon all right so the Django developer is happy this extends to all other Python frameworks so let's see if we can do the same for Ruby and particularly rails all right here we go so in rails I'm going to use the gem installer and I'm going to gem install the graph QL gem I'm also going to install rails graphical to avail ourselves of the graphical browser alright with that stuff installed let's go second verse same as the first I'm going to need to Gen rate a schema for graph QL in Ruby it's going to look roughly like this a schema I'm going to use the graph QL gem to create a new schema like so at the root of all good schemas is a query type what's in a query type a query type is a graph QL object type defined as follows it has a name has an optional description and it has some fields on it for instance I might have a person field which is of type person type it takes an argument like ID which is a string and in order to resolve a person I need to write some code now here's where I'm going to use active record with rails to pull my people out of the database active record exposes this API right I can say person dot find to find a person by their ID and in this case I can pull it straight out of args ID that should be enough to resolve a person all right more work to do what's in person type person type is also similarly a graphic you'll object it has a name and an optional description and it has some fields like a first name field which is of type string now I'm going to have to do a little bit of extra work graphing did some translation between the underscored version of this field and the camel cased version of the field that I have to do manually here I have to say the property you want to access this is actually called first underscore name whereas the field is called first capital end name same for last name and then for the other fields I'm not going to have to do any of that I can just say get email username and ID all right let's deal with the friends field now so I want to create a field I want it to be called friends I want it to be of type an array of these person type things and in order to resolve this I'm going to start from a person and I'm going to use the rails accessor person dot friends to go and grab that out of there all right that was a lot of typing and not a lot of running code what do you think let's give it a shot let's give it a shot I'm going to go to localhost 3000 where the rails app is running on my schema I have a person field it accepts an ID property and on that I can access first-name lastname I can get email and a username and I hope that I can reach into this friends Association and do the same and pull out my friend's first names and email executing this I pull out my friend Matz to the active record Association friends all right so the ruby developer is happy the Python developer is happy now I'm going to move over to a language that's near and dear to my heart we're going to do we're going to do something or other in JavaScript using node and Express right okay here we go round three for the JavaScript developer we're going to npm install the graphical gem and then i'm also going to install express graph QL which is a set of helpers that let you stand up a graph QL endpoint using express really easily alright let's do it so the node example has pretty much nothing i'm starting from I'm starting from serious zero here so let's create an index Tijs all right here's what I'm going to do I'm going to import Express I'm going to import as graph QL HTTP I'm going to install import this from Express graph QL I'm going to make an app I'm going to make an Express app I'm going to get that Express app to listen on port 5000 whatever I'm going to get that app to use this graph QL HTTP thing now I have to pass this graph QL HTTP thing a schema and I'm also going to tell it hey I'm in dev mode here so turn on graphical so that we can browse the schema all right what is a schema it's nothing until I define it in the following file which I will create schema jeaious alright I'm going to have to import a couple of things from the graph QL module graph QL schema for instance from the graph QL NPM module I want to export one of these new graph QL schemas scheme I scheme a pretty sure it's schemas and I'll great at the root of all grade schema starts a query type what's in a query type a query type is made up of a new graph QL object type which I will now import before it's too late an object is made up of a name and an optional description and some fields which I'm going to define as follows I want a person field and I want it to be of type person type I also wanted to take some arguments namely an ID argument of type graph QL string which I will import and then I need to resolve a person so I'm going to write a resolve method whoops now I didn't really think this through because I started this node example from scratch and I don't have a data layer here I started from literally nothing so where am I going to get data for a person well I want to point out something really remarkable about the resolve method in your average graph QL schema creation language resolve sure I can return something that conforms to person type but I can also return a promise that resolves to something that conforms to person type this is huge this opens up the entire world of asynchronous operations to this resolved method this means that in this resolved method I could like call the USPS API and I could like mail a letter somewhere when I get the response I could like open it and do stuff or I could like call the SMS API and send someone a text message and then when they text me back then I could do stuff with the text or something but I don't know I don't really have that those aren't really real things ooh but what I could do is I could make some HTTP requests to that Jango REST API that we were looking at before I could use something like the fetch API and I could hit some you know base URL because I know where that I know where that Jango a please it lives at localhost 8080 and the ID is going to be available through this args thing so that looks pretty legit that should craft a URL that hits the Jango API and you know then the response comes back I can parse the responses JSON and I can you know reach into that JSON and and grab the grab the person so I don't know could work especially if I import fetch all right none of this is going to work at all though without a person type so a person type is an object type that has a name and an optional description and some fields on it one of the fields is a first name and first name is of type graph QL string and I'm going to need to give this thing a little help to resolve it from a person because of that mismatch between camel casing and underscoring so that should that should do for first name this should do for last name and then for the other ones like email a username and ID that should be enough all right what are we going to do about this friends thing so friends is a field of type it's a graph QL list of this person type thing I'm going to import graph QL list before it's too late now how am I going to resolve my friends here's where things get interesting I have a resolve method it's going to take in a person but now what am I going to do person has a friend's property but that friend's property is just a list of URLs well down there I have this URL fetching thing so I wonder if I could maybe reuse that to load the nested friends by URL in the same way let's - shot let me let me do the right thing and and hoist this up and maybe create a helper method called you know get person by URL and get person by URL is going to look something like this something like this where I take the base URL and join it together with a relative URL pulls out the JSON returns a person okay looks legit so far wherever I want to use it I can use it like this where I say grab me people slash args ID alright and now back to the friend resolver so I know that person dot friends is a list of those URLs so I should just be able to map over it calling the get person by URL function each time that's going to return an array of promises that can go and grab that friend data supposedly all right well I don't know let's see if it works but you're not going to be satisfied if it works you're going to want proof let's take a look at those Django server logs what I should see here is I should see a bunch of requests going into the Django REST API if I hit localhost 5,000 graphical all right let's give it a shot looks like I have a person field so far so good it accepts an ID parameter and it looks like I have the usual suspects available like first name last name email username and a friend's field and I hope that I can pull a my user first name and email from my friends so if I run this I get three requests to the Django rest api and I see my friends Adrienne and Simon from the first exercise all right now you've opened up a completely new world where you can write a schema that hits a REST API Redis some kind of crazy asynchronous service any kind of service-oriented architecture a thrift API you can back that all with a single model at the graph QL schema and fetch them asynchronously now some of you have a smirk on your faces because you're thinking about how you can break my example what if I started querying for the friends of my friends and the friends of my friends of my friends and Turtles all the way down valid query may be valid response but what's going to happen whoa we just we just slammed that REST API for a whole bunch of duplicate requests we fetched people three a whole bunch of times people won a whole bunch of times that's not good that's bad so for this in the last five minutes that I believe that I have in Greta and 0 de Graaff kill in 30 minutes I'm going to show you our solution for this that we've open-sourced that github.com slash facebook slash data loader it's a read through cache that helps you with this use case and it looks something like this jumping back to the index j s graph QL HTTP I'm going to say okay listen when a request comes in I'm going to return you a configuration object that tells you how to kick off the query kick off the query to into the schema but also I want you to make available some context for me and particularly I want you to give me a couple of loaders that help me load data in a cached way what does a loaded look like loaders is going to be a bunch of stuff for right now I just have a person loader what's in a person loader a person loader is going to be one of these new data loader things here's how you configure data loader you give it a resolver and the resolver is designed as follows given an array of keys return me a promise that returns an array of things so if I can say for every one of those keys map over it and call that get person by URL function I'm going to pull that over from this file get person by URL base URL etc I'm going to pull that up to here so now I have get person by URL available and I'm going to import data loader like so alright we're thanks awesome alright so in recap graph kill is going to receive a request and it's going to pass a schema graph kiyul true and some loaders through this context thing loaders is just going to be a hash mapping person to this person loader thing and person loader is going to be a data loader that knows given an array of keys which in our case is just going to be an array of URLs how to return a promise that resolves all those things into the data that we're looking for using this get person by URL method alright how are we going to make use of that in the schema so wherever we were fetching before I was using this get person by URL method that I just evicted from this file so I'm going to pull these loaders through and I'm going to use loaders person load and pass it that URL that's the key to data loader up here where I'm saying person friends I used to be running a get person by URL for each but I should be able to pull forward this loaders thing from the context and then loaders person there's another method that data loader exposes called load many and since person dot friends is already an array of URLs that should be enough I should be able to load many URLs using a data loader all right syntax errors willing let's see what effect this has so Django server logs going to clear the screen and I'm going to try and execute this same query and see what happens we executed the same query we got the same response turtles all the way down but this time we only made exactly the number of requests that we needed to the backend API so that we get the performance characteristics that we needed to be able to an existing REST API using a graph QL schema in node and Express without ever tapping our back-end developers on the shoulder or asking them for favors this has been zero to graph QL in 30 minutes also known as zero to graph QL three times in roughly 10 minutes I hope that it's inspired you to try out these principles to build your build a graph kill schema atop your own infrastructure atop your own data layer to expose your universität ethroo graph kill so that you can start playing with technologies like like relay we're going to have a question and answer session after but thanks for your attention thanks for sticking with me through that and I hope you enjoyed the show welcome to Facebook and have a great rest of the day
Info
Channel: Steven Luscher
Views: 163,831
Rating: undefined out of 5
Keywords: ORM, SOA, REST, React, GraphQL, JavaScript, Facebook
Id: UBGzsb2UkeY
Channel Id: undefined
Length: 30min 13sec (1813 seconds)
Published: Mon Apr 25 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.