NextJS + GraphQL Blueprint: Professional Grade Setup

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
getting next js graphql and typescript all working together can be tricky but i think i've got your back hi i'm jack harrington a principal full stack software engineer and in this video we are going to set up a next.js server with graphql and it'll be completely typed from end to end and of course all the code is available to you on github for free so you can adapt it to your needs let's start back in the office so what we're going to do is going to build out a next.js server and then we're going to build an endpoint into that using apollo server micro and then on top of that we are going to define the schema which means the data types and the resolvers using a library called type graphql that allows us to define that schema using typescript classes then we're going to use the graphql code generator to build out graphql request functions that we'll send to the server using react query if it sounds complicated it's really not let me walk you through it right now okay so here's our app we've got a two-page app this is the home page and it's got a list of all of our adoptable dogs these are actually adoptable dogs from the oregon humane society so let's click on abby over here and see this is our detail page uh you can see that under the localhost 3000 dog abby and so basically you've got two queries here you've got a dog's query that gives you all of the dogs and then you've got a dog query where you give it a name and it gives you back that specific dog so we're going to do first is set up the server and get this home page and the dogs query running and get that all set up and then i'm going to show you the process of adding a new query to the system getting that through the generator and getting that into that second page that detail page and there you go okay so the first thing we need to do is go over to the terminal and get our application set up i'm going to go into my 2022 directory and then i'm going to run yarn create next app and just call it next gql dogs all right now i'm going to run vs code on that and here we go a pretty standard out of the box next js app let's you'll run yarn dev on that because we're doing development and we want hot module reloading and all the rest and now i will click on this and that gives us xjs nice okay good to go okay so having a look over at our app now we've got pages and then api and then within that we've got hello js and so what we're going to do is we're going to add a graphql endpoint here so basically you'll have the graphql server embedded in the next.js server and when you deploy this to versal you'll actually get a different cloud function for this route so you'll basically be running a cloud function graphql endpoint it just happens to be embedded in your app which makes it actually pretty easy so let's go and see what this api hello.js returns and it just returns name john doe and we can kind of see that over here basically you give next a function handler it takes a request which would have any parameters post body or whatever on it and a response and with the response we're sending a 200 along with some json and that's just going to go and send back some jsons really nice very easy way to make a route in next.js so what i'm going to do now is i'm going to convert this project to typescript so we're going to go and change this to hello.ts and watch next.js kind of freak out a little bit as we try and rerun it and it's going to tell us to do this add of typescript so we'll do that and now we'll rerun it okay it looks like we're good to go that api route still runs okay so now we're going to go build this graphql endpoint and to do that we're going to use an apollo micro server instance so that's basically a not a self-contained server but a server instance that's meant to be embedded inside of another server like this next.js server so we'll do that first and then we'll add on top of that a schema layer that will give us our dog's data but so let's start off with building out our apollo first and we'll do that by adding graphql and apollo server micro so graphql in this case is going to be used to parse the requests and the policy or micro is going to be the server extension that basically takes in the request from the request and then uses the schema and the resolvers to get the data and then formats that data for return okay so now that we've got that going i'm going to go over here and create a new file called graphql.ts which means that our graphql endpoint is going to be on slash api graphql and into that i'm going to bring our apollo server and since it's going to be a graphql request i don't want next.js actually trying to parse the body of this thing so i'm going to export a config out of this route that says that we don't want to enable the body parser next thing we want to do is start our server so i'll just do that's going to give us back our start server function and then finally we need that request handler so i'll go and give it another asynchronous function handler and it's going to await the start of that server and then once that is started it will then create a handler connected to the api route api graphql which is just going to handle our request and our response all right let's give this a try and see how that works and now we can go over to api graphql as opposed to hello see what happens all right so we need to add a module called micro so let's go do that and let's try it again and now it tells us it needs a schema okay let's make a schema so there's three different ways we can make a schema you could use the apollo version which is to give it a basically a piece of text and have it automatically take that piece of text and turn that into a schema on the fly you could use a library called graphql nexus which is kind of a functional approach to building out a schema one of the nice things about graphql nexus is it will actually export typescript types for you and that's a really solid option but i think i'm going to take one that's more object-oriented in this case i've already done the nexus thing so i'm going to do type graphql so let's get in here and do the getting started which will show us basically the kind of stuff that we're going to do here we're going to be able to define object types for example like this recipe here that's going to encapsulate our data and then we're going to be able to define classes that have the resolvers so you define the data and then the resolvers are what gives you the queries and mutations that you run against that data so in this case we're going to have one object type called dog and then it's going to have a dog resolver that has the dogs method on it as well as a dog method on it which gives you the specifics of a given dog so you can either get the array of dogs with dogs or the specifics of a single dog with dog so we need to do is add class validator type graphql and also reflect metadata so let's go and add those now one little gantry along the way the version of graphql needs to be synchronized exactly and i think it's like 15.3.0 might as well just fix that right now you know that graphql library it just it always gets me i don't know what's going on with that all right let's go back to the installation stuff and one thing we need to do is bring this import reflect metadata in and so i'll bring that into our graphql.ts file and then we need to go and make some modifications to the typescript configuration so bringing these in as well in particular this experimental decorators that we're bringing in that's going to enable all the at stuff the at decorators like at object at query at arg all that so we need to bring that in for sure and then we need a target es2018 at least and then i'm just going to add on this yes next async iterable and now in order to try this out what i need to do is go back over here to this graphql.ts file and for the moment we're just going to go and create a very simple schema right here so i'm going to bring in some things from type graphql including the schema builder and the decorators for resolver query arg and object type we'll use some of these right away to create a decorated class of dog so dog is going to have a one field in it so we need to bring in field as well as id and that field is giving me a name so every dog is going to have a name and so now we need to have a resolver to resolve a list of dogs so we'll create a resolver class so create a resolver for dogs called dog resolver it's a resolver that resolves dogs it's got one query on it it gives you back a list of dogs right here in this case it's got bo and lassie so just some hard-coded data right away just to make sure that this works and with that resolver then we need to build a schema so we're going to build a schema using that build schema function and we're just going to give it one resolver and that's that dog resolver and now we can pass that off to our server and see how that goes okay are you finally happy graphql let's see let's go back over here hit request ah okay so there's one last little gotcha along the way here and that's that we need top level await enabled and this is a webpack thing it's just a language feature and it's specifically around what we've done down here so we just need to go and enable that and the way that we do that is to go over here to the next config and then we need to modify the webpack configuration so to do that we add a key for webpack that takes a function which gets given the webpack configuration we then see if there's an experiments key on it if there isn't then we go and add one and we just set top level away in there to true and then we return the config okay let's try it again hit refresh hey cool okay so now i could query this over here although i've had kind of mixed luck with this so what i'm going to do instead is use a graphql extension that i have installed in my vs code called graphql nice one and it's got this ability to give me code hinting on graphql all i need to do is point it at the right server so in order to do that i'm going to go over here and create a new file called graphqlrc.json and into that i need to give it my schema location and that's just that api graphql endpoint that we just created so cool okay great so now let's go and experiment with this and see if we can actually query the dogs so i'm going to go here and create a new folder called source and within source we're going to have our graphql requests our api connector all that sort of stuff our generated stuff so i'm going to go and create a new folder in here and we'll call it graphql and this is where we're going to have our graphql request so we'll do the first one as dogs.graphql and i'm going to have a query called get dogs and we'll say we want dogs and within that we want the name now let's execute that wow cool that worked right then awesome okay so this is just a nice way to be able to make queries and test them right within your vs code you don't have to go out you want to go to the browser just really nice okay so now that we know that the basic flow here works i want to actually get like real data into this thing so in order to give you kind of a professional grade system i don't really want to go and keep on building a big old schema in here i think that would just be ugly so what i want to do instead is i want to go create a folder inside of source called schema and that's going to have the data as well as the object type for the dog as well as the resolver so first i'm going to bring in our dogs.json file and this is actual data from the oregon humane society i did the scraping on this so you know forgive me for the really bad json but basically it's an array of different dog objects and the important parts are like for example name sex breed agent weeks wait whatever okay so the next thing you need to do is model this as a dog object so to do that i'm going to create another file in here called dogs.ts for typescript and then bring in our dog definition and it's basically got the class for dog there is a dog attribute class in here shows you how to do kind of a nested class as well and all of this is decorated using the type graphql stuff the really cool part here actually is that the decorators sort of fall away if you just want to go and run unit tests against this that's fine uh you don't need necessarily to use these decorators and they kind of fall away if if you're not the actual like type graphql stuff that's actually looking at them okay so now we've got a definition of a dog it's got name it's got the description and the agent weeks and all of that sort of stuff and it's really nice all you need to do is just define okay the type type here is a string and the graphql type is a string and that's basically all you're going to need to do once you've got this defined then when we do our code generation and when we up on the ui all of those types are just going to get translated right through so it's going to be absolutely end-to-end typescript typing really nice okay so let's clean up a little bit and then go and create a resolver okay so i'll create a new file here called dogs.resolver.ts and into that i'm going to bring in again type graphql i'm also going to bring in our definition of a dog that we just created as well as the data for dogs now of course if you were doing this in production you probably wouldn't have just a flat file of dogs like this you might have sort of one of two sources if you've got a database i would recommend using something like prisma and if you've got apis you're talking to well you know you may have api adapters for that or you might just be using fetch to get those directly that's really up to you we're just going to use the dog so let's go create our dogs resolver and this is just like what we had before we're going to return an array of dogs a method called dogs and this is going to turn that data we got okay so now let's go over here to our graphql and we will go get rid of what we had before it's sort of placeholder stuff and we'll import the dog's resolver from the schema and let's give it another try here now i'm not going to even go look at it let's go over here to our dogs graphql and see if we can get some more stuff out of here for example breed all right look at that abby is an alaskan malamute siberian husky cool all right but we want more than this for our homepage so let's go and extend onto this query we'll bring in the name debri the age the image so you can put an image on the home page sex weight and the adoption fee all right now we've got our query we've got our api endpoint that gives us our graphql it's all working great what now we need to do is get it onto the client and the way that we wanted to do that is by using the graphql request library on top of react query so rack query is going to manage doing the mechanics of the caching and all that and then graphql request is going to do the formatting of the request for us so to do this in a cool way we're going to use the graphql code generator so what is the graphql code generator with the graphql code generator is an extensible plugin based code generator that one goes and gets a graphql schema for you in this case our schema and it also takes a bunch of inputs which would be graphql queries and mutations we've got a query right here the get dogs query and then it applies a bunch of plugins to them and in this case we are going to use it to actually go and build the graphql request methods for us super cool okay so let's go back over into our terminal and i'm going to go and create a new terminal in here and within that terminal i'm going to first bring in the graphql code generator the command line interface or cli as well as the typescript plugin which is pretty standard pretty much all the plugins i've seen require this then we're going to bring in the operations plugin again this is sort of a standard plugin then we're going to bring in the graphql request plugin and this is the thing that's actually going to build our graphql request functions for us automatically it's very cool and then finally i'm going to bring in the react query plugin now to configure this what you need to do is you need to go create a codegen.yaml file so i'll go up to the top level here and we're going to configure our code generator so codegen.yaml and the first thing you need to do is tell it where the scheme is and the schema is in the same place that we used for graphql our cjsun we're going to use it right here it's that api graphql then you're going to tell it where your queries and mutations are in this case they are in source and anywhere within source any file is named graphql you can make a gql whatever you want and then you want to tell what to generate so you're going to say we want to generate a file in under source under a new directory called generated it'll create that for us called graphql.ts and within that we want to tell it what plugins to use what things to generate so the first plugin we want to use is the typescript plugin so we want to say create the typescript types as well as typescript operations and finally the most important part which would be those graphql requests so this is bringing in those plugins and you can also configure them here but we're not going to make any configuration changes just going to use the out of the box all right so now we want to go and actually run it we want to do the generation so let's go over here to our package.json file go into scripts and we're going to add a new script for generations that's just going to call graphql code gen so let's do yarn and then generate and there we go cool okay so it went off it hit our api server it got the schema back it looked to see if there were any graphql files around there were and it generated some outputs for that so let's see what it generated it went over here to generate ah graphql.ts just like we asked it to and now if you scroll down here we can see that it has get dogs and it's got the query variables and any headers and all that it's got the gql document and it's got the types so it's automatically maintained all of that and it's even done some checking so if i go over here to dogs ql and i were to say name of dog doesn't exist that's a field does not exist so let's try and generate that again let's see boom blows up i could look at the error code i'm pretty much gonna know that it's you know that field doesn't exist on there so it's really nice it's actually validating to make sure that your query is actually correct cool okay so let's generate it one more time just make sure it's all good okay cool okay let's go back over here and now that we've got our graphql request now we need to go and actually make that request from our index page so let's go and stop this server and then bring in react query and also graphql request all right so that looks good so what we're going to do is we are going to server side render these pages so we're actually going to make the request on the server side and then let that data flow through to the client we're not going to make the request on the client and so what we need to do is kind of have a query client that is shared between the two things i'm going to make a source here a source file called api.ts and it's basically going to be our entry point for our api and into that i'm going to bring the graphql client from graphql request as well as a query client from react query and i'm going to bring in that sdk from that generated file that we just created and that sdk has get dogs in it then i'm going to create our graphql client and point it at our local endpoint and then i'm going to export from here get dogs and we're going to get that back by doing get sdk and giving it that gql client so that's how the graphql request library knows what url to hit is by giving it that graphql client and then finally we're going to create a react query query client and this is going to be basically kind of shared between the server and the client code and it's going to have some defaults on there that say well when you're doing queries then don't refetch on mount or window focus or reconnect and that basically just keeps react query from immediately requesting the data again once it hits the client rec query just tends to do that and the best thing to do is just kind of turn it off if you want to make sure that you are an ssr only application all right now let's go over to our app js file and into this i'm going to import the query client that we just created as well as the query client provider which is from react query which is going to provide that query client down during both ssr rendering and also on the client as well as this hydrate thing what hydrate's going to do is it's all going to allow us to pre-fetch the query during server-side rendering and then high dehydrated and then rehydrate it on the client and so to do all that we need to need to wrap this component in this query client provider and give it our query client and then also bring in this hydrate component and give it the dehydrated state and this is what we're going to provide from the page props that we're going to create during the server side render so let's go over here and go to index.js and start with that so now i'm just i'm just going to pair this down a little bit so we get rid of this class name in here take this down to the studs all right cool and in fact we'll get rid of some of that css and we need that we're going to be using mantine for that so get out all that okay cool and now we want to do our ssr so let's go and import so first off we're going to have our react query and we're going to bring in use query with that as long as well as that dehydrate function which is going to take our like dehydrated fetch result i don't know okay and then rehydrate it on the client and then we're going to bring in query client and get dogs so get dogs is what was returned to us from that generated code and now we're going to do our server-side props so server-side props is an exported function it's asynchronous and it returns a set of props so what are we going to do that well we're going to call our get dogs and we're going to do that by calling prefetch query on that query client so we're going to fetch the data and we're going to kind of load it into that client and that client you can do as many queries as you want here and prefetch them all and then they're basically just waiting there for when the component on the page during client-side time right client-side rendering time asks for them so now we've pre-fetched our get dogs and then we're going to create that dehydrated state prop by dehydrating the query client so this dehydrated state here matches this dehydrated state here that comes in with the page props call that whatever you want i'm just going to call it dehydrated state and now to get access to that i'm going to use that use query hook in the component code to go and get our data so let's take a look and see if we get some data we'll just do a json stringify here so let's start up the server again and we'll go to the home page and we've got our cool data awesome okay very nice so now we've got end and typing and a really nice way of specifying graphql queries and getting them all the way out to the client all right so let's put a nice face on this and to do that i'm going to bring in this component library called manteen mantine i'm not sure it might be actually named after a pokemon for all i know i think there is a mantine pokemon which is kind of ironic since the number of videos i've done on pokemon anyway a viewer suggested that this was a pretty cool component library and i agree actually i think it's kind of neat certainly lightweight i like the way it's factored so let's try it out let's see how it looks okay so i'm going to stop the server here and then we're going to install our mantine libraries so that includes mantine core manti next which is for nexjs as well as the form components and also the hooks so kind of a nicely factored library there and then in addition to that i'm going to bring in an icon library called tabler icons they're wrapped in react svg icons i don't know how many libraries there are that have sdvg live icons now it is crazy and so the first thing we want to do is kind of wrap all of the pages right so we need an app shell it's going to have a nav bar it's going to have a header on the top and actually mantine provides a nap shell thing right out of the box so app shell and i'm just going to you know use effectively this but you know i'll walk you through it so what i want to do is create a layout component so i'll create a new directory at the top level called components and within that i'll create a new file called layout.tsx and then i'm going to bring in an app shell layout so this is going to use that app shell mantine component it's going to put a header on there and that component is going then going to encapsulate whatever children that you give it now we need a navbar so i'm going to set a navbar property that has a link using the next js link functionality to home again all this stuff is on github you don't really need to watch me kind of fumble around at typing it out you can go and try this out for yourself just by downloading it and then we'll have a header on the top and the header will say oregon humane adoptable dogs it'll have a hamburger that will open and close the side menu and yeah let's take a look so let's hit save here and then rerun our server and let's see have we created ourselves a nice little home page and no we haven't because we actually haven't brought in that layout so let's go back over here to our app and then bring in the layout and then we need to wrap our component in our layout so let's try that see that works hey look at that nice it's even responsive i think ah cool i mean this whole section here isn't exactly responsive so but but the old layout is responsive so that's good all right so now we need to go and clean up this section in the middle there and that really just comes down to using their grid layout and their cards to go and nicely format all these dogs so let's go over here to our index page and do that all right so good dogs deserve a good layout so in this case we're gonna have a grid it's gonna be a responsive grid within that responsive grid it's kind of cards the cards are gonna have image an image of the dog as well as some text if you are a material person this is the mantine version of typography and then title again kind of a typography variant all right so let's go replace the stringify with actually a nice piece of layout so this is going to have a div then it's going to have a grid that grid is going to go through all the data the dogs returned from the data it's then going to put a column in there where it's on small size there's gonna be 12 across out of 12 which means full medium six meaning there's gonna be side by side two and then large is gonna be four meaning three across we'll put together a nice little key there and give it some padding uh mantine's one of those things kind of like chakra where you can just put margin and padding right in there on the each one of the components you know p is for padding so p in this case is just going to give you padding on every axis of five you could do pb for padding on the bottom pt for padding on top m would be for margin mt for margin on top and all that kind of stuff link is the next.js link and then card is the mankind version of a card you can have sections we have a title on there the image is a responsive image it's kind of nice and then we're just gonna put in some text and uh let's see let's see how it looks okay oh pretty oh so cute okay so we got abby over here so there you go so this is basically part one done this is all the way from the ui back to the graphql layer we've got hinting so if i were to go here and for example each one of these f's is a dog and all of that like agent weeks and breed and fee and all that that's all hinted for me so it's great i've got nice type safety all the way from the back end to the front end so now what i want to do is i want to kind of show you all of this again basically walk you through the process one more time by going and creating the sub page so if i do for example abby here it's going to go to dog abby and currently we get a 404 out of that so we're going to create a new route for that and a new route means a new piece of data so we need to go all the way back to the api server and add the capability of getting just a particular dog then we need to go and grab add a query for that then we need to rerun that generator and then we need to go and put together the page that's going to show that dog and so it's basically going to show you what we've done already but just again and we're going to add on the ability to have arguments so that's kind of nice all right so one more time this time with feeling let's go back over here to our source and into our schema and so we need a new resolver we got the data already we know what a dog is now we just need to get a dog query so to do that we just create another method on this class and that method is named dog unsurprisingly it's also a query it returns a dog it could be null which is what that nullable troll true means that we didn't find a dog with that name and it takes an argument so we use a decorator to specify that we have a name that is a graphql type of string and that gives a map to a parameter to this method called name and this is going to return a dog or undefined and we'll just use an array finder to go and find that dog with that particular name and if we don't find it then we throw an error if we do find a dog then we return the dog okay so now that we've got that let's restart our server and then we'll go and create a new graphql file and this new graphql file is going to be our by name getter marked by name query so it's going to be dog by name graphql and it's got a query in there dog by name it's going to take a name which is a string the exclamation point here means that it's required it's then going to pass on that name to the dog function that we just created and it's going to get back some of the data that we're going to show on the page or all the data we're going to show on the page so let's try this out let's actually let's execute query here and one of the things that this plugin does if you've got parameters like in this case name it asks you for what that is so i'm going to say abby i think that was one of the dogs and yes we get our alaskan malamute siberian husky named abby oh she's very cute okay so that's good and now we need to rerun our graphql generator right because we still have just get dogs we don't have this new dog by name so let's go back over here to our other terminal and hit generate again and there you go when you know it now i've got dog by name awesome cool so we are well done the pike all right next thing we need to do now we've got our support in the api we know that it works we ran it and we've got our graphql request method let's go and create our route so if i go back over here and it's dog abby so what i need in the pages directory is a new folder called dog and then under that we're going to take a parameterized page so in this case the parameter is the name so you put that in brackets and then tsx and that's going to take the name in this case abby and map it to the incoming parameter of name now before we get too far ahead we do need to go over here to our api file and make sure that our dog by name method is also exported from that git sdk and the api and then we're going to bring in our imports so we're going to bring in react as well as dehydrate and use query like we did before and also some stuff from mantine basically exactly the same thing we had before with the addition of a button and then we're going to bring in our api so we're going to bring that query client like we did before but also we're going to bring in dog by name this time because now it's exported from that api and we'll do our get server side props but this time we're going to take parameters because those parameters have the name of the dog so we will pre-fetch our query of dog by name and assign that to dog and we're going to give it the incoming params name and then just like we did before we're going to return the dehydrated state but we're also going to send across the parameters so in this case that name parameter because we need that to line up between those the client and the server side rendering for the use query stuff so now let's create our page and we will do our use query to go and get the data and all i'm going to do at this point is just return and i'll do that json stringify trick again the data so let's see what we get back and let's export that as the default and rerun it and there we go cool we've got our data now all we need to do is format it so the first thing to do is make sure that we have the case covered where we didn't get a dog back so we'll just have a no dog found div that gets put out there and then we'll just start rewriting this ui so just bound the whole thing in a grid and then within that the first thing is going to be the image so this is going to be the image along with an alt for the dog's name oh guys so cute okay now we need a column that's got all their data and their details so put another column and it'll start off with the dog name there we go abby and we have another grid within this which has kind of a tabular feel to it so it's got the age the number of ages and the age of weeks breeds so and so forth let's uh save that out see how that looks oh that looks really nice age is 78 six weeks again let's go pick another dog so we can see another dog here so all right let's go look at milo oh my god oh just so cute 11 weeks old wow all right so how do we adopt milo well we need one more button down here and that's the adopt button so let's add another column where we have a button full width adopt and then the dog's name so dubbed milo yes we do so there we go so very cool it's responsive just a a really nice little app and a good starter point for you so if you are looking to do graphql next js have it all ssr'd and have it type safe from start to finish then this is a nice little starting point for you you can just pull out all of these beautiful pieces of dog data that we got in here and replace it with whatever schema that you have you do it all in an object oriented style and away you go good setup for you so that setup in the beginning was a little bit tricky getting typescript and graphql and xjs all working together but i think by the end we got something that's really workable but if you think you can do better i'd love to hear about it in the comments section down below as well as any comments or questions that you have if you like the video hit that like button if you really like the video hit the subscribe button and click on that bell and be notified the next time a new blue collar coder video comes out
Info
Channel: Jack Herrington
Views: 9,903
Rating: undefined out of 5
Keywords: graphql tutorial, graphql, graphql server, apollo graphql, nextjs, server side rendering, graphql react, ssr, graphql resolvers, next.js, Type GraphQL, GraphQL Code Generation, react-query and graphql-request, GraphQL solution for NextJS, NextJS + GraphQL, blue collar coder, Mantine, next js graphql typescript setup, next js typescript, Next js + graphql professional grade setup, jack herrington next js, Apollo Server Micro, next js react query, type GrahpQL, nextjs graphql setup
Id: XzE-PzALyDc
Channel Id: undefined
Length: 38min 6sec (2286 seconds)
Published: Mon Apr 04 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.