1. Introduction to Code-First GraphQL APIs
Hey, I'm Ryan. Today I want to talk about a different approach to building GraphQL servers. I'll discuss code-first GraphQL APIs with Nexus Schema. As a GraphQL developer advocate at Prisma, we make it easy to work with databases and provide type-safe database access. Find me on Twitter @ryanchenke.
Hey, I'm Ryan. And today I want to talk to you about a way to build GraphQL servers that looks a little bit different than maybe the typical approach that people might take. The approach of building a schema-first GraphQL API.
I'm going to talk about code-first GraphQL APIs, specifically with Nexus Schema. So my name is Ryan Chenke. I am a GraphQL developer advocate at Prisma. And at Prisma, we deal with databases. We make it really easy to get started with a database to have a really nice ORM around your database. We give you type-safe database access, which is very nice to work with, especially if you're working with TypeScript in Node.js. You can find me there on Twitter. I'm at ryanchenke on Twitter.
2. Building GraphQL APIs with Schema-First Approach
When building a GraphQL API, we often start with a schema-first approach using the schema definition language. However, this approach can present challenges and complexities that may be better addressed with a different approach.
So let's talk about building GraphQL APIs. When we come to build a GraphQL API, and typically when we're first learning how to build a GraphQL API, we take the approach of what we call schema-first, and we use what's called the schema definition language approach to build a GraphQL server.
And so many of us have seen this if we've gone through the initial kind of getting started phases, or even if we've built full-out GraphQL APIs, where we start with a schema definition language, and we define our types and our input types and all that, and then we have a set of resolvers that map up to it. But this isn't the only way to do it. Even though it's easy to get going with, it does kind of present some challenges that we'll have to deal with along the way.
Most examples show how to do this schema definition language first approach, especially if you follow the Apollo tutorials, for example. You're going to see this STL-first way of building a GraphQL server, and it's easy to get started with, but ultimately it's going to lead to maybe some complexities that are better dealt with in a different approach. This is what it looks like. You would have your schema definition language. Here we've got a type of post and three fields. We've got the ID, title, and body. You may be familiar with this. This might feel quite comfortable. We've then got our root query type, where we are returning a list of posts.
3. Schema Definition and Code-First Approach
When building a GraphQL server, you need both a schema definition language and resolvers. However, working with them separately can lead to issues, such as modularization challenges and frequent context switching. Additional tooling is required for an SDL first approach. Alternatively, the code-first approach allows defining the GraphQL schema in code, providing more flexibility.
Now, with a schema definition language, this isn't all you need when you go to write your server. You also need a set of resolvers. For this example, we need to map together a resolver for our root query type, which can return those posts. It's two different pieces of code.
So, what are these issues? Well, when we're working with schemas and resolvers, separately, they're in different places. They're in two different spots in the file system. We get into issues around modularization. So, if we want to have a large GraphQL API, oftentimes, we want to break up our schema into smaller kind of sub-modules. And this is doable, but it kind of presents some challenges when it comes to mapping all of that together in the end, tying them all together into one root server.
So, you've got your resolvers in one place, you've got your schema in another place, and you've got to switch back and forth between the two. You've got to do a lot of context switching when you're writing your code. And that context switching, I think, comes with a cost. You are working in one kind of language at one time and then another at another time. And, you know, this might get to be somewhat trivial if you're well experienced, but even for those of us who have a lot of experience with it, it does come at a cost switching back and forth between these two kinds of modes of thinking.
You also will need some tooling when you're going into an SDL first approach. You need tooling to make your schema definition language, you know, even just code highlighted appropriately. You need some extensions in your code editor. You need some things to modularize those, your schema and the resolvers that go along with them. So there's a need for additional tooling to come along for the ride if you're going to work in this way.
We can take a different approach. We can take the code first approach to writing GraphQL APIs. And what that looks like is a little, something like this, this is Nexus in this example, and we're defining a GraphQL schema here, but we're doing it all in code. So this happens to be TypeScript. We've got this thing called object type from Nexus schema, which allows us to define a type in this case, it's that post type. And then we've got this definition method where we can say we want an ID named ID. That's what we're doing there when we do t dot ID. And then we want some strings t dot string with title and body. So this gives us our schema definition language, but we've done it in code.
4. Benefits of Code-First Approach
So what's the benefit of this? Well, if we hop over to our root query type, it gets really interesting. What we're doing here is we're saying that on the root query type, we want a field called posts, and we are telling it how to resolve with the data for that post field right here in place. So we've done all the work to come up with a GraphQL schema, and the associated resolver for the post type in this case, all in the same spot. This is just kind of one file that we're working in, no need to context switch between different types of code, and we've accomplished everything we need right here.
5. Nexus Schema-powered GraphQL API
Let's take a look at a basic Nexus schema-powered GraphQL API using Apollo Server. With Nexus Schema, we can define our query type and its resolution in one spot, eliminating the need for separation.
So let's take a look at how this might work. Let's do a demo. This here is a basic Nexus schema-powered GraphQL API, and it's using Apollo Server. Ultimately, we need a server to serve this thing up, but we're constructing this API with Nexus Schema. And so what it looks like if we go over to the browser, we've got just this simple hello world example at play right now. And so that gives us an API all based on this code right here. We're defining our query type. We're telling it how to resolve all in one spot. No need to separate those things out.
6. Creating API for Planets with Nexus Schema
Let's create an API for planets using the object type in Nexus schema. Define the planet type with an ID, name, and type fields. Include the planet type in the types array to make it available. On the root query type, add a list field called planets and specify the planet type to resolve with. Set a resolver function to return an array of planet objects. In the GraphQL playground, query the planets with id, name, and type fields.
So I figured what we'll do, because we're here at GraphQL Galaxy, let's see how we can come up with a little bit of an API for planets so we can talk about the planets in our solar system. To do that, we would do a constants and maybe call it planets, and that's going to equal something called object type. We want to define an object type. So this would be like, if you were in your schema definition language, and you were defining a type for something.
That comes out of Nexus schema, we have to give it a name, so let's call it planets. And then we give it some definition. And the definition, again, is something where we do like T.id to give ourselves an ID. So it's a type of ID and the name for it is going to be ID. And then let's have a string field, and we'll give the planet name, and another string field to give the planet a type. All right. So we've got our planet type. We have to put it in here into the types array when we make our schema, has to go in there so that it becomes available.
And then on our root query type now, we can define something in addition to this string field that we've got. And we can say give us a list field called planets. Let's say we want to have something that gives us a list of planets. We have to tell it what type to resolve with. We want to resolve with the planet type. And then we can set a resolver. So the resolver, the resolved function might look like this. We can return an array. We'll have some objects in there. Let's say id will be 1. And name can be earth. And type can be rocky. Something like that. So if we're now back over in our GraphQL playground, let's see if we can get that out. So we can do planets. Do id, name, and type. There we go. So we've got our planets array coming back.
7. Integrating a Real Database with Prisma
We can easily integrate a real database into our API using Prisma. By running 'npx prisma init', we create a Prisma file that provides a schema. We can choose different databases, such as SQLite, and define our model, including the id, name, and type fields. Running 'npx prisma db push' inserts the dev.db into Prisma, allowing us to explore the database using 'npx prisma studio'.
And we didn't need to, again, define a schema and then define resolvers. It's all happening just in one spot here. So really powerful way to get everything into the mix to make our API.
Let's see how we can get a real database in here. And we can do that really easily with Prisma. Prisma happens to tie in really well to GraphQL and to Nexus in particular. So I've got Prisma installed. And to get it going, I can do npx prisma init, like that. And what that will do is create this Prisma file, which gives me a schema, this schema.prisma file.
And there's a bunch of different databases supported. I'm going to use SQLite, so a file system database in this case, just for the purposes of the demo. And that's going to point to a file called dev.db. And then I can create a model. And the model will be planets. This kind of maps to a table that we'll create in the database. And we'll have an id, we'll set it as type string. And we'll say that this is going to be the id, this is going to be the primary key for this table. And the default value, we'll give it a default, can be a collision resistant universal id. We'll want name as a string. And we will want type as a string as well. That's all we need for our database model.
And then we can do this. We can do npx prisma db push. And this is actually a preview feature right now. So we'll just pass that flag. And if we do that, we get a dev.db inserted into our Prisma. This is our database itself for SQLite. And let's take a look at this database. npx prisma studio gives us a graphical user interface to take a look at what's inside our database. And we can see we've got our planet table.
8. Adding Records and Accessing the Database
We can add records for Earth, Mars, and Jupiter to our database. By importing Prisma and using the Prisma Clients, we can access the planets in our database and return them in our GraphQL API. This code-first approach provides the benefits of a type-safe way to access the database and the ability to generate the schema definition language and types as artifacts.
We can add some records. So let's say Earth type is Rocky. We can add a couple more. Let's say Mars. That's Rocky as well. And we'll add one last one, Jupiter, is gas giant.
Alright, we'll save those three changes. So that's in our database. We're good to go there. And so now over in our server.ts, let's bring in Prisma to actually do this work. We can import Prisma Clients from at Prisma Clients. And then we can say const Prisma equals a new Prisma Clients.
We can take a look at what's available on Prisma if we just do a dot and immediately we're taken to this planet property. And this maps over to our database. We get basically all the type information generated for us that we would need to do our queries. So if we want to resolve with the planets from our database, we can do this. We will return Prisma planets find many. And if we do that, and we go back over to our graphical playgrounds, let's hit go on that. And we get all the planets coming out our database.
So immediately here, we've got the benefits of the GraphQL API written in a code first way and a type safe way to access our database. One final thing that will show is how we would get that SDL produced as an artifact from this code first approach. And to do that, we can do something here on our make schema, where we define some outputs. And there are two that we might be interested in, one would be the schema. And for this, let's do this, we'll say the directory name slash generated slash schema.graphql, schema.graphql. So that's one thing we might want. And we also might want TypeGen, that will generate the types for us. And for this, we can say maybe types.ts. And what we should get if I save this, immediately what we'll see is this generated folder pops up here. If we take a look, we've got the schema definition language that maps to the schema we've defined with Nexus. So basically, we've got all of the benefits of a code first approach.
9. Benefits of Code-First Approach
We don't have to move around throughout our file system. We can define everything in the same place, both our schema and our resolvers, but we also get the schema for our actual schema portion of our GraphQL API produced for us, and we can use this elsewhere. And then we get a set of types that come here that we can use across our application. And where it gets really interesting, especially with Prisma in the mix, is Prisma gives us the type information for our API, essentially, our database. And so we can use this type of planet, for example, in various places across our application. The benefit here is a code first approach is going to give us an easy way to stay in the same spot, not have to context switch, not have to bring extra tooling, and ultimately give us a really nice developer experience when building a GraphQL API. If you want to get the slides for this talk, you can go to this link. It's a bitly link, slash GraphQL Galaxy will get you to the slides. You can check us out. You can check me out on Twitter, if you'd like. Ryan Shanky is my handle on Twitter. You can check out Prisma on Twitter, it's at Prisma. Or go to Prisma.io to find out more if you're interested in Prisma or Nexus, because Prisma takes care of Nexus schema as a contributor, slash, author, and you can find out more about all of this if you check us out on Twitter, or go to Prisma.io. Thank you.
We don't have to move around throughout our file system. We can define everything in the same place, both our schema and our resolvers, but we also get the schema for our actual schema portion of our GraphQL API produced for us, and we can use this elsewhere. And then we get a set of types that come here that we can use across our application. And where it gets really interesting, especially with Prisma in the mix, is Prisma gives us the type information for our API, essentially, our database. And so we can use this type of planet, for example, in various places across our application.
So again, the benefit here is a code first approach is going to give us an easy way to stay in the same spot, not have to context switch, not have to bring extra tooling, and ultimately give us a really nice developer experience when building a GraphQL API.
So that is it for the demo. And that is it for the talk. If you want to get the slides for this talk, you can go to this link. It's a bitly link, slash GraphQL Galaxy will get you to the slides. You can check us out. You can check me out on Twitter, if you'd like. Ryan Shanky is my handle on Twitter. You can check out Prisma on Twitter, it's at Prisma. Or go to Prisma.io to find out more if you're interested in Prisma or Nexus, because Prisma takes care of Nexus schema as a contributor, slash, author, and you can find out more about all of this if you check us out on Twitter, or go to Prisma.io. Thank you.
10. Discussion on Nexus and Prisma
Hey. Hello, how are you? I'm doing well. You? I'm good. That was a wonderful talk. Thank you so much. Thank you. Appreciate it. Awesome. It looks like most of the people got it right. If you liked Ryan's talk, please send virtual clap emojis to show your love and support for Ryan. On Discord, by the way. For someone who is new to Nexus or new to Prisma tooling, what's something that is super cool to you? Prisma provides a type-safe database client, migration support, and a studio client for data visualization. It allows writing database queries without writing SQL and ensures query correctness through type safety.
Hey. Hello, how are you? I'm doing well. You? I'm good. That was a wonderful talk. Thank you so much. Thank you. Appreciate it. Awesome.
So what do you think of the result? Were they surprising from the question? I think that's a good proportion of the respondents that got it correct. I've done this question in other events, this similar question, and it's about equal. It's kind of that 80-20 thing, I think. So you know, 80% of people got it correct. And I think each of the individual benefits of Nexus that were seen there in the options, that's just a small proportion, I think, of what's actually available for benefits with Nexus. Those are some of the biggest ones, I think, that most people like about Nexus, and there are many more. But yeah, I was happy to see most people picked up on the fact that it was all of the above. That's awesome.
So it looks like most of the people got it right. Also, just a reminder, if you liked Ryan's talk, please send virtual clap emojis to show your love and support for Ryan. On Discord, by the way. So we will be looking at a few questions that a little birdie usually drops on Discord. But I have a question before that. I haven't personally used Nexus. For someone who is new to Nexus or new to Prisma tooling, what's something that is super cool to you? I know that you recently started working at Prisma and joined the DevRel team recently, and you might have been looking at it from a perspective of someone who's new to these tools. So do you have any thoughts on that? What's something that a beginner would look at? Yeah, so I mean, Prisma, what you get with Prisma is like a type safe database client, type safe database access client, and a whole bunch of other stuff too. There's a lot of tooling, you can get a studio client where you can visualize your data and there's migration support and all this kind of stuff. What I really like about Prisma is that I really want to work with relational databases, but the typical ways you do so writing SQL by hand, there are other options for ORMs and stuff. But if you're reaching for other ORMs or writing SQL by hand, the experiences that I've had anyway have not been great with those solutions. So Prisma was the first thing that I use where I was like, this is really great. I can write a database query without actually writing any SQL and I can make sure that my query is correct before I even run my code because it's all type safe. So the Prisma clients won't really let you do anything that you're not supposed to do with your database.
11. Benefits of Nexus and Code-First Approach
If you've constructed your database and set up your models the way you want, you can sort of bank on it being a really safe experience as you're writing your code. And it gives me more confidence when I'm putting my databases out into the real world. As for Nexus itself, it's a nice experience because it's nice to not have to go back and forth between writing SDL and your resolvers. It's nice to have everything in one place. It's a good combination, I think.
If you've constructed your database and set up your models the way you want, you can sort of bank on it being a really safe experience as you're writing your code. And it gives me more confidence when I'm putting my databases out into the real world and I think that's what a lot of people like. As for Nexus itself, I hadn't really used the code first approach much before I checked out Nexus when I came on board at Prisma. And it's a nice experience because like I mentioned in the slides and in the question, it's nice to not have to go back and forth between writing SDL and your resolvers. It's nice to have everything in one place. It's nice to have the generated artifacts that you get from Nexus like the schema definition language, which you can go plug into other tooling and stuff like that. Overall, it's just been a really pleasant experience I would say working with Nexus for code first GraphQL APIs plus Prisma. It's a good combination, I think.
12. Discussion on Nexus and GraphQL Maturity
I think there's room for improvement in the configuration process of Nexus instances. It would be great to have more automatic management and easier configuration. As for what excites me about GraphQL, I'm thrilled about its stage of maturity and the opportunities it brings. GraphQL is becoming more established, stable, and battle-tested. There's less apprehension from organizations, and more knowledge sharing is happening within the community.
That's a great answer. Also, I'm thinking out loud processing all the information that you gave from your talk and also from your answer. What's one thing that you think would make Nexus a whole lot better or one challenge that you face while using it is there something like that?
Yeah, I mean, there's a little bit of configuration stuff that you have to do if you want to work with like plugins, for example, and in certain scenarios, have typings kind of work out for you. So there's a little bit that can be done, I think, to make the whole configuration task a little bit easier, have things a little bit more automatically managed for you because there are a couple of sticking points that you can run into when you're setting things up. Once you overcome those, it's smooth sailing. But yeah, I think, you know, it's certainly something to look at in the future for making it a better developer experience is having more easily configured Nexus instances, that kind of thing.
Absolutely. I think, yeah, I think that's right. That's a great answer. I can see that we currently don't have any questions for you on Discord. So before wrapping this up, my last question for Ryan would be, what's something that excites you about GraphQL? Since we are at this lovely conference that's GraphQL Galaxy, there's a galaxy of GraphQL enthusiasts looking at the possibilities that GraphQL is bringing to the table. What's something that excites you? Something that you're looking forward to?
Yeah, well, something that I've been thinking about is how GraphQL is coming to a stage. What seems like to me is kind of a stage of maturity where it's like, there's a lot of hype about GraphQL in the early days, and there's still a lot of hype, but there was a lot of hype. People were figuring things out. Not everything that you would want to build into an application was really in the GraphQL spec. There is only a small slice of things that would be in the spec that you would go and apply to libraries and stuff like that. So people were figuring things out on their own, in their own libraries and stuff like that. And I think what we're coming to now is this place where things are being agreed upon more and more, conventions are being agreed upon, things are making their way into the spec now. That's got a lot of work going on it. So we're reaching this stage of maturity, I think, with GraphQL, which it's exciting for two reasons. I think because the stage that GraphQL is at, it's still got a lot of hype behind it, but it's also maybe you could consider it a lot more stable. There's less apprehension from organizations to reach out for GraphQL because it's more established now, there's more work being done on it. So I think that's exciting because there's more opportunities for GraphQL developers to work with GraphQL in new jobs if they want to. I personally love working with it, so if I have chances to work with people on GraphQL projects, it's a great thing. And, yeah, so the maturity of it, it's sort of coming around to being like a kind of a, it's more and more battle-tested now, I think it's a great thing. So that excites me quite a bit. And, you know, I think there's like a lot more knowledge sharing that's going on within the community too now. And I'm thinking of things like Marc-André Giroud's book that came out about building GraphQL servers and how to build a GraphQL app, you know, that scales. That is a great example of someone who has gone through really kind of like the most kind of intense GraphQL application you could build at places like Shopify and GitHub and sharing that knowledge out. So I'm really excited for all of the knowledge sharing that's happening, which gets people into the GraphQL world more and more.
13. Excitement about GraphQL's Growth
GraphQL is maturing and growing as a technology, along with the community and the tooling that uses it. It's exciting to see developers working on GraphQL and the progress being made. Thank you for being here and for the great Q&A session, Ryan.
Yeah definitely, I think I can relate to your answer right there. Because something like a technology as young as GraphQL is, it's maturing now and it's great to see that as the community is growing, as GraphQL as a technology itself is growing, all the tooling that uses GraphQL you know, all these amazing solutions and products that uses GraphQL, they're growing too and it's a really wholesome experience to see that happen.
Every time I see a GraphQL job posting it just excites me that there are actual developers working on this stuff and working on these things I think. Yeah. Yeah definitely. Agreed. That's great, I'm excited to be here. Thank you so much.
It was a pleasure to have you with us and that was an amazing Q&A session with you. Thank you Ryan. Thanks, appreciate it. Thank you.