Videos → End-to-end Type-Safe GraphQL Apps
Description
Discover all the benefits of using GraphQL adding End-to-end Type-Safety to your app with this live-coding talk. At the end of such, you’ll want to refactor your codebase in order to take all the advantages of TypeScript, GraphQL & React working together on a SpaceX demo 🚀
Chapters
- Introduction and Speaker Announcement 0:00
- Welcoming Carlos Rufo 0:56
- Introduction and Kudos to JavaScript Bangkok 1:19
- About Carlos and Today's Agenda 2:22
- Dev Jokes 3:06
- Introduction to GraphQL 4:31
- Why GraphQL? Comparison with REST 5:08
- Why TypeScript Loves GraphQL 7:44
- Live Coding: GraphQL API and Testing (Server-Side) 9:12
- Generating a REST API with GraphQL Schema 10:03
- GraphQL Server Setup and Context 11:16
- GraphQL Schema: Single Source of Truth 12:12
- GraphQL Resolvers: Fetching and Returning Data 13:51
- GraphQL Playground Demo: Introspection and Avoiding Over/Under-Fetching 14:48
- Tooling and TypeScript 17:30
- Evolving the API: Adding rocketByName Query 18:01
- Using TypeScript to Maintain API Consistency 19:56
- Live Coding: Client-Side with React and Apollo 22:34
- Client-Side Setup and Data Display 24:00
- Adding Ships to the UI: Developer Experience with GraphQL 25:23
- Wrap Up and Call to Action 28:26
Transcript
These community-maintained transcripts may contain inaccuracies. Please submit any corrections on GitHub.
Introduction and Speaker Announcement0:00
Next is the topic of End-to-end Type-Safe GraphQL Apps by Mr. Carlos Rufo from Spain, the organizer of GraphQL from Hong Kong. So please stay tuned.
If any one of you would like to talk personally to each of the speakers once they finished their sessions, they will be standby in the Q&A room. The Q&A room is out of the theater, turn right and you will see the room, okay?
Welcoming Carlos Rufo0:56
Next, ladies and gentlemen, a big round of applause to welcome Mr. Carlos Rufo from Spain, the organizer of GraphQL from Hong Kong!
Introduction and Kudos to JavaScript Bangkok1:19
Wow, that's incredible. How many people here? That's great.
How's everyone doing? Come on, guys. I know this is after lunch and we good, but how's everyone doing here?
What? Okay, I have something for you guys today. So let me just start here. So before introduce myself,
I really wanna say kudos to JavaScript Bangkok and thanks to you all. Thanks to speakers, sponsors, organizers, but especially to you all because without you, we couldn't be here. And I don't know if you have realized this yet, but I think we are around like 700, 800 people
gathering together for a JavaScript conference. And I think, if I'm not wrong, we're in the largest JavaScript conference in Asia. So please, a round of applause for everyone of you here.
About Carlos and Today's Agenda2:22
So great. A bit about myself. So I'm Carlos, I'm a software consultant, I'm the GraphQL Hong Kong organizer, and last year, I created the SpaceX GraphQL API. You can find me on the internet @swcarlosrj. I gonna go super quickly with the slides and we are gonna just going full in live coding demo. So I'm gonna go to a GraphQL intro for those that they don't know what is GraphQL yet. Then we are gonna see why TypeScript loves GraphQL
and then we are gonna do a server and client-side live coding. But before start, I think we like tech and we love stuff, but we like to have fun here, right?
Dev Jokes3:06
So we are gonna start with some dev jokes. So you can go to github.com/shrutikapoor08/devjoke and check a lot of super fun jokes. So my first question is, how do you comfort a JavaScript bug? Any guess in the room? Nobody? So basically, you console it.
And also we can see this, right? Like, you are in your IDE and everything looks great. It's Friday, 4 PM, push to production, and then you see your CEO is calling you, 7 PM, "Hey, man, what's going on here? Runtime error." So we are gonna see later in the live coding demo that how TypeScript is gonna solve these problems. I have another question for you. Why do functions always break up?
Any guess here? So basically, because they have constant arguments. This is not a good one, yeah. And yeah, I couldn't be here without this one. I added a joke.
If you don't find it you can go. Okay, and the last joke and then we go through the demo. So, what did the developer say to the repository? And I'm pretty sure that you guys, you have said this to your colleagues a lot of times. So, it says, "Fork you."
Introduction to GraphQL4:31
Okay, so let's start with an intro to GraphQL. I have a question for you all. Please raise your hand. How many of you have heard or just know about what is GraphQL? Please raise your hand. Okay, I cannot see that much in the top. Okay, I will say like a 40%, 50%, which is a lot. And now, the second question is like, how many of you are working with GraphQL in production in your companies?
Okay, so it's like 20%, yeah, 20% kind of. I'm pretty sure that next year is going to be like double, triple that. I'm almost sure.
Why GraphQL? Comparison with REST5:08
Great, so we're going to go quickly through what, why, and how GraphQL. So, first, GraphQL is a, and this is super important, please, it's not a library, it's not a fancy new framework. It's a language-agnostic specification to build APIs. So, please remember, if you don't know GraphQL yet: GraphQL, specification, and APIs. And you can see in the bottom all the languages where you can implement a solution for creating GraphQL APIs. Next, again, it's important, GraphQL is not a library, it's not a framework. It's a graph query language to build APIs, where we are going to describe our data. We are going to ask for whatever we want, avoiding over-fetching, and then we are going to get predictable results.
Next, we are going to see the main features, which are: - It's strongly typed with a GraphQL schema definition - It is introspectable by specification - It's based in queries to fetch data, mutation to mutate data, and subscription to subscribe to data - It's efficient and reusable, avoiding over-fetching and under-fetching data - Transport agnostic - It improves a lot the product development Great, and here, I left some resources to learn.
And I'm going to leave the slide later with a QR code. So, please check it out. But before going into any framework or library, please
check the core fundamentals in graphql.org. It's super important to understand what is GraphQL and which problems it solves in order to start using it. Why we should consider GraphQL, like if we compare with REST, for example. We have several topics. I'm going to go super fast. Type system: we have to define any single field that we are going to expose, but also its types. It's predictable by default. So, we are going to be able to introspect those types, and also reuse those types. We're going to see later all these topics in the live coding. There are two common issues: over-fetching and under-fetching. Over-fetching, let's define them. It's fetch more data that the client actually needs. So, as a client, I would like to ask for what I need and just get that, whether I'm in my mobile client, tablet client, or desktop client.
Under-fetching, instead, is fetch not enough data that the client actually needs. I think it could be really nice if we could ask for nested resources within our data sources, and then return back all the data in one single server call.
I would like to have auto-generated types and always up-to-date documentations. And I would like to move faster with powerful dev tools. Great, how we are going to do that? We are going to see in the live coding demo in just two minutes.
Why TypeScript Loves GraphQL7:44
So, now we are going to see why TypeScript loves GraphQL. TypeScript, if you don't know yet, is a type superset of JavaScript that compiles to plain JavaScript. So, JavaScript with types. And yeah, we want types, even if you don't like them yet. Types, we agree, are really good with GraphQL because it starts and ends with JavaScript. It contains such a strong tooling for large applications. TypeScript is backed from Microsoft, and GraphQL, in the beginning, was backed by Facebook, and now both communities are working hard on it. And I would like to call it the state-of-the-art of JavaScript, because every single week we've got new features and new companies and new contributors like
creating really cool stuff around these technologies. So, we would like to introspect our API with GraphQL, but also introspect our codebase with TypeScript. So, we are going to have a single source of truth with our GraphQL schema, that is going to contain all our types and all the fields that we are going to expose to our API. And then, we are going to extend those types to both or the different layers of our application, which are backend and frontend. And that's what we are going to do in the live coding. You see, the type generator, GraphQL Codegen, is an open-source library created by The Guild. So, anybody can go and just use it. And we are going to auto-generate the TypeScript types based on our GraphQL schema for both backend and frontend. So, I think we get.
Live Coding: GraphQL API and Testing (Server-Side)9:12
Live coding, the agenda. We're going to see first what is a GraphQL API and how you can test it. Then we are going to jump into the IDE coding real code and see to the server first and then go to the client. And we are going to be using the SpaceX GraphQL API. I know, because there's a lot of rockets. So I'm going to my IDE.
And we are going to start here the fun thing. I'm using hotspot with my phone, so we're going to see how everything works. And I don't have much space here, but I can just do this. Awesome. So first, we're going to open the code base. I'm going to make sure that everything looks okay. So we're going to have the server and the client. So we're going to go to server, we're going to go to our source folder and we are going to open the index. So we can check here, we are going to have a GraphQL server and a REST server.
That's going to be interesting.
Generating a REST API with GraphQL Schema10:03
So before that, I'm going to go to my server side and I'm going to execute 𝚢𝚊𝚛𝚗 𝚜𝚝𝚊𝚛𝚝. So we are going to run our server. Great. So we can see here two servers, the REST and the GraphQL. And it's going to be interesting because, even if we are here to talk about GraphQL, I'm going to show you some really cool stuff. So I'm going to go to my localhost 4000.
I'm not cheating anyone here, you can see it. And I'm going to go to REST. And what is happening here is, if we let's say get some rockets. I like rockets. So we're going to have one, two, three, four rockets. And we are going to contain all the information, for example, this is the Falcon Heavy rocket,
probably here in the bottom, we can find it. So basically, what is happening here, if we go to our REST file, is that within 34 lines of code,
we are going to be able to auto-generate a REST API, fully typed and fully documented, only passing our GraphQL schema, which is incredible. So I'm using this open source Sofa API to do this. If you have any question about it, in the slides, everything is open source, so you can go to the repo and see how this was implemented.
GraphQL Server Setup and Context11:16
But today we are here to talk about GraphQL. So in the GraphQL application, we are going to pass the node instance and also a configuration that is going to contain the schema and the context. So let's go to the context first. So the context is going to contain some utils.
So it's going to contain some sorting, finding, and limiting functions, and also a database. So for you to understand how we are going to do the live coding today, we are going to be using a SpaceX MongoDB public database where we are going to connect with a MongoDB client and we are going to just fetch data because it's read only. So you can see here the URL, you can go later and just check by yourself all the tables and all the data. Great. And then we are going to check here utils, the types. We don't have just types yet, we have like just the context, everything is any. And then we are going to have the schema, which is our single source of truth and is the most important part of our applications.
GraphQL Schema: Single Source of Truth12:12
So in the schema, we might see that we've got capsules, and launches, and histories, and missions,
and rockets. So in the rockets, I'm going to go to type definitions. As we have mentioned before, in GraphQL, we are going to define query entry points, whether are queries to fetch data, mutation to mutate data, or subscription to subscribe to data. And we are going to specify which field we want to use. So in this case, if we want to fetch rockets, as we have done in REST as a /rockets,
in GraphQL, we are going to specify the field name, but also which data we are going to return. In this case when we are asking for just one single rocket, we are going to get rocket, we are going to specify the ID, and that ID is going to be required because makes sense. In order to go to database with that ID, which is coming from the params, and then I'm going to just return one single rocket. And it's important because when you are specifying the data that you return, GraphQL is going to ensure you that your API
API call is going to be valid only if those types match. And that's going to be good and we are going to see later why. So then we can see that rocket is going to contain different graphical primitive types. As you know in JavaScript, you can find booleans, integers, numbers or string or text. Or also it could contain graphical complex types.
As for example, rocket first stage, right? We can go here and we can see all its subtypes, right? So you might ask where this is like, okay, you are going to specify that we are going to get rockets, but where these rockets are coming from, right?
GraphQL Resolvers: Fetching and Returning Data13:51
So that's where now we are going to see where we are going to resolve and return the data in our resolvers. So in our resolvers, if you see here the code base, we are going to have a query. When we are asking for query, we are going to specify the different query fields that we have implementing in our graphical schema. And here in the rocket, I'm pretty sure even if you don't know JavaScript that you are in a JavaScript conference and you are going to follow this. So we are going to get the context, we are going to get the database from the context. We are going to go to our rocket collection. We are going to do filtering and finding,
sorting, skipping and limiting. We are going to convert to array and return the data. And with the rocket ID, we are going to do the same, only that we are going to get the ID that is required for our second argument in our resolver function. And then we are going to filter by ID, we are going to get just one element and we are going to destructure that element. So here we are going to get an object. So then if we go to GraphQL in order to understand
GraphQL Playground Demo: Introspection and Avoiding Over/Under-Fetching14:48
what is GraphQL, this is what you get.
This is nice because let's say even I don't know anything about GraphQL at all, but I know that I can have a type system and it's going to be introspectable and I'm going to avoid over-fetching and under-fetching. So let's do all of it in one.
Let's say that I don't know what is going on here, but I know that doing control space, I'm going to have autocompletion about all my types and it's going to be introspectable because I'm able to see everything. So I'm going to get histories and from those histories, I'm going to get the ID. I don't know, I'm going to just try to find a name. There's no name, probably title. Then this history is going to be in the history table. Now I'm going to go to my launch table. I'm going to get launches for every single history and then from every single launch, I'm going to get rocket. And you are going to see how I'm accessing all the different tables in my database and I'm sending back just one request.
So I think I'm going to go to flight and I can even create alias for it. So this is going to be a launch. Let me check, launch and this is going to be a flight. And then for the flight, I'm going to get the ID. And then I'm going to get the name that is going to be a mission name. So let's put name here. And then we are going to get a rocket and that rocket is going to contain ID and name
and we can do the cost per launch putting another alias. So now if we open the console here, we are going to see how we are going through all these different databases. What is happening is GraphQL, we are sending this smart query. We are going to the history table. When we are getting this data, we are before sending it back, so we don't have to do any extra round trip HTTP calls. We are going again to the database, we are getting all this information and when everything is ready, we are going to send it back. So we can check this is going to be super expensive. So let me just limit to a couple of them,
just two of them. And we are going to see here with one round trip HTTP call, we are going to get and go through different database tables, get all this information.
So we are going to process all our data in our physical servers instead of going to different round trip network calls to get that stuff. So you can see here one round trip HTTP call and you are going to get a JSON, which is no type. And then we are going to see how we can extend the types to our front side and back end side and the data in this case, two histories and you can see the launch and the rocket and all the information. I don't know if it's big enough, but you can kind of see here, right. So this is GraphQL, avoiding over-fetching, under-fetching, we've got automatically generated type,
fully documented, always up to date. And now we are going to see the tooling, right?
Tooling and TypeScript17:30
And TypeScript. Cool. Let me go back here and now what we are going to do is evolve our API. That's I think what we do like every day, right? But before that, let me just show you guys that you can also do a rocket by ID and this is going to be a Falcon Heavy and then
we are going to just get the name and the ID. The ID and the name. Awesome. That's will be up. So we got the data back.
Evolving the API: Adding rocketByName Query18:01
And now we are going to just evolve our API. So I'm going to go here. I'm going to go to my Visual Code extension, GitHub extension in order to check my pull requests. So I can see here that there is a pull request which is called, let me check if this going to open, okay. Is add rocket by name query field. So I'm going to check out the branch. We are going to see the diff. This is the diff. We can see here that we have include a new query
entry point field called rocketByName that its input is a name. This is a string that's going to be required. But also we have see here that we have changed the ID from lowercase to uppercase, which means that we might have some problems. So let's see what's going on here. So we can go to our type def again. We can see the new evolution of our API. And maybe we have to implement the business logic about this new query entry point field. Great. So before anything, I'm going to go back to my API. I'm going to run it. And I'm going to test. I'm going to just run my CI with all my tests in order to see that everything is working with my new evolution. And then we go back to the API. And then we can check that the rockets are working. Just let me copy this. And this is working. We're going to get like four rockets. And then we go to the rocket by ID.
GraphQL is going to tell me, hey, it's not ID lowercase anymore, it's ID uppercase. So I can just do auto completion here and execute the query. And I'm getting a null, but I know that this data is in my database and that ID is correct. So what is going on here? So basically what is going on is if we go to the resolvers, in the resolvers, we might see that we are accessing to ID lowercase. So we are finding for null. Finding for null is going to return null. So that means that we are exposing our APIs
to millions of users. Let's say that we are Facebook or Twitter or Airbnb
with an inconsistent state of our APIs. And this is going to lead to break a lot of applications.
Using TypeScript to Maintain API Consistency19:56
So we are in 2020 and we have solution for solving this problem. So basically what we are going to do is I'm going to go to the server. I'm going to run just GraphQL gen. So I'm going to auto generate all my type, all the TypeScript that based in my GraphQL schema. And I'm going to type my resolvers in order to have auto completion and run checks in compile time in my codebase.
So you can see here, we have generate almost 5,000 types.
And even if you don't like types, but your CTO is telling you that you have to use types, the first type that you want to use are those that you don't have to write at all. You are going to auto generate them from your single source of truth. And from there, you are going to just type your codebase. So basically what we are going to do right now in order to fix this is go to the resolvers. And in the resolvers, we are going to just go to our query and do query resolvers.resolvers.
And we can see here the checks. So that means if now I try to run again my API,
my API is not going to run. And that's great because I don't want to expose my API when it's not consistent.
So now I try to go to the API and this is not working at all. So in order to fix it quickly and jump into the client, I'm going to just remove this, do control space. I'm going to get my ID. This is going to be I'm going to find ID by ID. And then let's say that now I have to evolve my resolvers to include the new query entry point field that I defined before, which is rocketByName. So basically what I'm going to do is control space. I'm going to find rocketByName. Oh, it's here, perfect. And I don't know about you guys, but what I usually do in my day-to-day is just copy and paste stuff. So I just going to copy this. I'm going to paste it here. And even I'm going to have auto completion about the arguments for my new type because I already generate its types. So I can just remove this, do control space. I'm going to get the name. And then I'm going to go here, and I'm going to do just name. So now if I save this, if I go back and I run again my API,
if I'm not getting any compile time error in my IDE, it means that my API is going to be consistent. So now when I'm going back, if I reload, I can just check my rocket. Now it's working. And then I can go to my rocketByName. And we can check that now this name, and now we are going to find for Falcon nine.
And then we can add another field here, for example, active. And we are going to get the data and everything is going to work as expected. That's great. And this is incredible developer experience. So now to finish this talk,
Live Coding: Client-Side with React and Apollo22:34
now I'm going to go to the client side. Let me just go back to the initial state of the app and check the client in a bit. And then we are done here. So let me just go here, exit review mode. And then let's go to the client. And first we are going to yarn start. Start. And then we can just go here and go to the client side. Also, we're going to have just two files, index and app. If you don't know React, I'm pretty sure that you're going to understand this. So, first, let's check the app. So, we have an array where we are going to display all
the launches for SpaceX. So, we are going to have here the mission name, the rocket name, the description, and one image. And I don't know if you guys like SpaceX or not, you like rockets, but for me, it's just incredible what these guys are doing. You can see the scale of the car in the bottom and see the rockets, which is just wow, incredible. So, okay, going back. Right. So, we got Apollo Client from Apollo hooks. We are passing the GraphQL URL. Then we are going to use the Apollo provider, passing the client instance as a prop. And we are going to just import the app using React Lazy. And then in the app, even if you don't know React, you are going to see here that we've got HTML.jsx,
and we've got some data, and we are going to display the mission name, the rocket name, the details, and the image.
Client-Side Setup and Data Display24:00
Where this data is coming from? Basically, we are going to use useQuery from Apollo React Hook, and we are going to get the data. You can see here already it's any, so we didn't have types yet. And then we are going to have our query, right? So, in order to finish, because probably I'm running out of time, what I'm going to do is first, I'm going
to go to my extensions, activate the Apollo GraphQL
Visual Code extension in order to have autocompletion inside of my IDE, which is just incredible because you don't have to jump into browser and IDE. And then, so basically what we have to do is go to Apollo config. We have to specify the GraphQL API URL. I'm going to save it. You are going to see here how we are going to load the schema and all the fields and the types. And then also, what I'm going to do is I'm going to auto-generate all my types based on my GraphQL queries. So, I'm going to go to the client. I'm going to send GraphQL gen. We are going to auto-generate the types. So, we are going to see here if everything goes well, that is true. So, we are loading the GraphQL schema, and yeah, let's hope that it's going to work. And so, first, let's say that now I want to browse my API. I don't want to check documentation. I don't want to do console.log anymore. I want to introspect my API from my IDE and then auto-generate the types for it. So, here we can see the types. And in this case, we've got a 500 kind of, but we can see our getLaunches with our launchpads and all our data here.
Adding Ships to the UI: Developer Experience with GraphQL25:23
Great. So, basically now, let's say that you are starting tomorrow in a new company, and the front-end lead tells you, "Okay, you got to display the ships." So, I'm going to show you guys how a production-ready
application with GraphQL helps you to achieve a superb developer experience. So, what I'm going to do first is like, do control space within my editor. I'm going to have autocompletion about all my fields available in my API. So, I'm going to just look for ships. I'm going to know that this is a complex type, so I might have to say ID, name, and let me check more,
it's going to be a port. Even I can create the alias for it, and then I'm going to do an image. So, now when I'm saving this, I'm going to auto-generate the types for the new evolution of my query. So, we are going to see here, hopefully, the types generated. And then only we have to go to our return function. Here, we are going to set the div. So, we can see the new ships with the information. And so, basically now, you don't have to check that stuff, just to show you guys, but now what you can do is just basically to finish this talk, it's going to be do control space. You are going to find, hopefully here, you should find the ships, that is not for some strange reason. Because, okay, perfect. Before that, so let's say that we have this, and this is the same that we have in a JSON, right? So, everything looks great, and you don't know rocket, it's 4:00 p.m., you don't know, man. And then you go to your UI, boom, like exploding
your face, right? So, we can solve this because we have types for do that. So, we are going to type our return data, and then we are going to have a compile-time check in order to fix this. Because you can spend hours, you are not going to differentiate between A and O. So, you are going to just fix it. And then to finish this talk, I just going to click in control space. I'm going to have the ships. And then I just can go here, and I'm going to get my ships. I know that this is, TypeScript knows that this is an array. So, I do dot, and I'm going to get all the functions that I can apply to arrays. I'm going to do some filter, and then I'm going to just map it. And this is going to be kind of, let me check if I can do quickly, and this is going to be a div. And even I can introspect the complex type of the ship. So, I can see here, doing control space, that I'm going to have the name. I'm going to get the port, and I'm going to get the image. And basically, in order to finish, I just going to, don't forget the key. This is super important in terms of performance. And then we are going to do an H2.
This is going to be the name. I'm going to put here a bold, and then bold, and then
we are going to just finish. So, name, H3, this is going to be the port. And to finish, it's going to be the, if I can do that,
it's going to be the image that is going to contain the image. And then we are going to do a width of 200 here.
So, now when I'm saving this, if I'm not having any error in my IDE, means that when I'm switching back to the app, and it's working, please give me an applause because the live coding is difficult always with GraphQL and server calls and TypeScript.
Wrap Up and Call to Action28:26
So, now if I'm going back, everything is displayed as we have implemented here. So, let's finger cross, and yes, we have here all
the ships for every single launch.
Thanks. We can see all the ships here. Cool. So, yeah. So, that's everything for me. If you want to learn more about GraphQL, there is an incredible meetup here in Bangkok. It's been running for a year and a half. This last week, they've got a meetup and a workshop for free. They provide pizza, they provide everything. So, go to meetup.com/graphql-bangkok. For the new members, if you click and join, we are going to raffle two t-shirts for free. And same, if you want to learn more, in two weeks, there is going to happen the GraphQL largest conference
in Asia. It's going to happen this year in Bangalore, India. Like 500 people, two days of talks, one dedicated workshop, more than 25 speakers from around the world, PayPal, AWS, all the best companies. And yeah, it was a pleasure to be here with you.
I'm really looking forward to meeting all of you. I'm going to be around. Please, let's chat about GraphQL, JavaScript. I'm super fun about those technologies. So, there you got the slides. And if you have any questions, please reach me on Twitter @swcarlosrj. Thank you so much. Thank you. Thank you, Carlos. I told to my friends that you are as handsome like Orlando Bloom.