We all love GraphQL, but it can be daunting to get a server up and running and keep your code organized, maintainable, and testable over the long term. No more! Come watch as I go from an empty directory to a fully fledged GraphQL API in minutes flat. Plus, see how easy it is to use and create directives to clean up your code even more. You're gonna love GraphQL even more once you make things Redwood Easy!
From GraphQL Zero to GraphQL Hero with RedwoodJS
From:

GraphQL Galaxy 2021
Transcription
Hey everyone, Tom Pressenwerner here with a simple question for you. What's the easiest way to get a graphql api up and running? We all love graphql, but it can feel a little daunting sometimes to get a project going. And here's another question. Can it be easy and maintainable? Can you keep things in an orderly fashion over the long term? Well, that's where Redwood.js comes in. Redwood.js is a full stack app framework, perfect for everything from rapid prototyping to building startups. I've been working on it for the past two years, and I think it's become something really useful, both on the front end and the back end. Let me show you what a Redwood.js application looks like. On the front end, we have a web application, single page app, react based. And on the back end, we have a node.js based api written in javascript or typescript. The front end talks to the back end using apollo Client and speaks graphql to the back end where we use graphql Helix and Envelop to create the graphql server. In your business logic, you'll use prisma to talk to a database. While Redwood.js provides the front end and the back end, today I'm going to focus mostly on the back end and creating the graphql api. So let's go look at some code. Okay, so the first thing I'm going to do is create a new Redwood.js app using yarn create Redwood app. And I'm going to make a simple music app, so I'm going to call it tracks. This is going to fetch all the dependencies, run yarn install, etc. Usually takes a little while, so let me speed that up for you. There we go. I'm going to go into that directory and I'm going to open up a VS code from there. First thing I'm going to do, I'm going to grab a terminal window here and I'm going to make this a Git repository so you can more easily see what files I'm changing. Okay. So here's a Redwood.js application folder structure. We've got the website that I talked about, the front end, and we've got the backside api. And in here we can find in the DB folder schema.prisma. This is the prisma schema file that's going to tell us what our database looks like. There's some sample data in here. For me, I want to have an artist table and that's just going to have a name that is a string and I'm also going to have an album table that will contain album information. That's going to have an ID, that's an int, it's an ID, and it'll be auto-increment. And it's going to have a title that's a string and it's going to have a number of likes, that's an int. Now I want to be able to connect these two so that my artists can have multiple albums. So I'm going to say I'm going to have an album and that's going to be album array. When I save this, boom, we get some nice things that prisma does for us. It'll connect these two for us and I'm just going to rename what it calls this and I'm going to say it's always going to have one of these connections. So that's it for now, just an artist and a number of albums as the schema. Now let's boot up our application so that we can see what it looks like. We haven't really done much yet, the schema doesn't actually exist in a database yet. But to boot up the application, we'll run yarn redwood dev. This is going to start both the backend and the frontend so that we can see the full application connected. And we'll be mostly interested in the backend in this talk, but it's useful to know that the frontend exists. So here's the frontend, right now it's just a placeholder. The backend lives on 8911 port slash graphql. And in here we can see the schema of what's already there so far. There's not too much, some scalers, some introspection stuff. There's really not much going on yet as we would expect. So what do we want to do next? We have our schema, we need to actually put that into a database. So let's run a migration to do that. So I'll run yarn redwood prisma because we're using prisma. Migrate dev, and that's going to take our schema, it's going to look at what changed and it's going to create a migration for that and put it in a migrations folder that will appear here in a second once I give it a name. And here it is. So I'm going to say add artist and album. So now we'll create this migrations folder for us. This allows us to easily then deploy these migrations into a production server eventually. And so now we have the schema established inside the database. Okay, great. But it's not very interesting until there's some data. So we can put some data, some sample data into the database using this seed file here. I've handily got some seed data over here. So I'm just going to wipe out this file. I'm going to paste in mine. This is just a bunch of sample data that it's going to input in there. And I can put that into the database using yarn redwood prisma db seed. So that'll run that file and just enter that sample data into the database so that we can play with it. So there we go. That's done. And now we need a way to look at the data. And wouldn't it be handy to have some graphql functions to be able to list out and maybe create new ones. Luckily, Redwood JS has exactly what we need. And so we'll run yarn redwood g for generate. And we're going to create a scaffold, which is going to be the stuff on the front end and the back end in order to create the CRUD operations that'll get us started. We can modify from there. So create a scaffold for artist. And I'll create one for album. And now once we have those, let's look over in our graphql again at our schema, you'll see now that there's a bunch more stuff in there. So we have a bunch of queries around albums and artists as well as creating and deleting and updating. So let's run one of them and see what we got. Let's look at albums. And we can say, give me the title and the number of likes. Execute that. And here we go. We've got a bunch of albums in the database that we can play around with. And we've got graphql functions in order to be able to see all of that stuff all in a couple of minutes. This is really what it is to work in the Redwood world. We try to make all of this stuff super easy. We really focus on developer experience, getting you to where you want to be as quickly as possible. OK, that's all fine and good. You've got your schema. But what did we generate? Is that stuff any good? Well, let's go look. So let's look in the source graphql albums. And in here, we find the SDL, the graphql Schema Definition Language, that represents what our graphql api looks like. So we see the album type. We have some queries. And we have the other stuff that you've already seen in the schema. Similarly, we have another file where the artist is defined. And indeed, you can use types across these things. We stitch them together for you. So we make this part of creating a graphql api very easy. Really excellent organization. Everything's in its place. Everything is separated exactly where you want it to be. So how are these implemented? Let's look in services. A service is a chunk of your graphql api split up by functionality. And so here we can see, again, let's look at albums, albums.js. And in here, you'll see a bunch of regular functions exported. They each take arguments, perhaps. And this will look familiar to you. It looks very similar to what you might put in your resolvers if you're creating one big giant resolvers object. The nice thing about Redwood.js is that we will automatically map the names of your queries and mutations in your SDL file to javascript or typescript functions that are exported. So for instance, in the SDL, you have the albums query. And in the albums.js service implementation, you have an albums function. And this is how we match them up. So we simply look for exported functions of the same name. And that's how we map them. And you'll see why this becomes important later on. So okay, here's the implementation. These are simply prisma calls that you make. Simple stuff, not too complicated. And if you want to change this stuff, you can go in and customize this to your heart's content. If you want to get rid of the ability to create an album via graphql, you can simply delete this implementation, delete the statement from the SDL, and you're done. Now let's look at what it looks like to create another query. So let's go into albums and say, I want to have the ability to find popular albums. So I'll create a new query called pop albums. And it's going to return an array of album. And none of those will be null. And I'm going to add this require auth directive on it, which I will show you what that's for later on. It's underlined here because it says service not implemented. So we have some nice things that we do in VS Code to help you out. And one of these is to let you know that, hey, you define this in the SDL, but you haven't written the service for it yet. Okay, great. So let's go write the service implementation, the resolver for this. It's going to look a lot like albums. So let's export const pop albums. And that's going to be a function, no arguments. And it's going to return the DB of the album table. I'm going to find many of those. And I'm going to, let's say we want to order all of the albums by likes in reverse, descending, and then take the first 10 of those. So with prisma, we can say order by likes descending and take the first 10 of those. So let's save that. And let's go over and see if that's now available after the server reloads. So we should expect to see pop albums. And indeed, there it is. And let's get back the title and the likes, execute that. And so here we go. Now we have some albums and the likes are ordered by descending order. And let's see, there's only 10 of them. So great. We've implemented a new function, a new graphql query. As easy as that. It makes sense. We export a function. It's very easy to sort of separate it from all of the other ones. And it's as easy as that. So this is the magic of Redwood that you've seen so far. It's easy as that to get your graphql api up and running, add something to it. Now let's go a little bit further. Let's say I want to add a new service and add something on that. But I'll do it by hand this time. So in our graphql, I'm going to add something. I'm going to call it info. It'll be our info service. And in there, all we have to do is we, just like the other ones, export a const. It's called schema and it's going to be GQL, graphql. And in there we have our query type that will extend. And I want to create something that's going to give us back a single album, the most popular album. So I'll call it the top album. And it's simply going to reply with a album and I need my require auth directive. So let's save that. It's the error, no implementation. So let's give ourselves a little quick shortcut here. And this is going to create the implementation for us and stub it out now in the info service. We'll clean this up a little bit, no arguments. And so you remember how those functions, the resolver functions are now just regular javascript functions. Well, that means we can import them. So let's import pop albums from the album service. And because we already have that available, let's just pull the first one off of there. So let's get all of the popular albums. We're going to call that, we have to wait on it because it's async. And then let's return albums zero. Let's just return the first one. And of course we use the wait. So we have to make this function async. So let's save that. And now we would expect after the server restarts that we will have a new query called top album. And so let's see what the title and the number of likes are in there. Oops, likes, plural. So here we go. We've got 9808 likes. That's the top album, just as we expect. So that was pretty cool, right? We can import those resolver functions and use them other places and services. So it really gives you a way to separate out your backend functionality, your business logic in a logical way, which gives you long-term maintainability and makes it really easy to look at and understand what's going on. Another cool thing about graphql is that, of course, you can traverse things. So let's say we want to know who the artist is and get their name. We can execute that. Boom, there's their name. And of course we can go deeper. We can say, maybe I'm on my homepage and I want to show the top album and recommend to you some of the related albums. So I'll say, okay, well, what are your albums of this artist? And I want the title and the number of likes so I can display those on the homepage. And it appears that I named this thing incorrectly. Actually called album. Okay. So here we go. Now we can see the related albums. Don't you love graphql? So cool, isn't it? But wait, there's more. Let's talk about those directives that we saw. So remember albums and the require auth directive. Well, let's see what that does. We in Redwood land, we call these secure services. That means that out of the box, every graphql query and mutation that you do is going to be secured by default. Now we haven't installed any authentication and Redwood JS makes it really easy to add third-party auth integrations like OAuth or Netlify Auth, or you can roll your own and have it stored in your own database. And we have an entire functionality called dbauth to do that. So when you do that, require auth will actually start doing something. Right now, it will just allow everything to come through as you've seen here. There's no authentication necessary. Well, let's look at how require auth is implemented. And that's up here in the directives folder. So require auth comes in. It says, here's what it looks like in the SDL land. This gets merged in. And this is a validation directive, which means it's going to either accept or reject your access. And in here, we're calling this application require auth, which is up here, and it just pulls something from source lib auth, this require auth. So let's look at that. Source lib auth. And in here is require auth, and it calls is authenticated, which just returns true. So if we come in here and we say, well, instead of doing that, I'm going to fake being an authentication service. What if I'm not authenticated, and I'm going to throw a new authentication error, and it's just going to say, nope. OK. So now we will expect that our queries aren't going to work. Now we've forced that there is no, everything is unauthenticated. So let's try running this again. Here we go. Nope, unauthenticated. And now nothing that uses require auth is going to work. So let's say we wanted to get album and get the title and the likes. Nope. graphql says nope, right, because it's behind require auth. OK. Well, what if we don't want authentication? What if this query is on the home page and you don't need to be authenticated? Well, that's why we have another directive called skip auth. So albums query, let's tell it that it can skip auth now because it's publicly available. So now let's run that query. Hey, there we go. It works again. So authentication can be built right into your SDL files. You have it available on a very fine-grained basis by query, and you'll see it on mutations. And that then is integrated with all of our authentication techniques, making it super easy. So what if you want to create your own? There's another type of directive called a transformer directive, and I'm going to show you what that means. So let's generate one. yarn redwood generate directive. And let's say I want to, if you have a subscription to my service, then you're going to get all the data you want. But if you don't have a subscription, then I want to limit the number of records that you can get back. So I'm going to call this a sub limiter because it's a subscription limiter. So sub limiter. This is going to then generate a new directive. I have to tell it I want a transformer directive. It's going to generate a stub for me. And here it is. So I mean, this is a real implementation. It's got a bunch of comments in here, but the bulk of it is there's a transform. It receives the result value as it already is. And it lets you modify it. So in here, instead of pretending this is a string, which mine will not be, mine will be arrays, I can say I want to slice it and restrict it to only three items. Now this is going to do it for everyone. If I had some more logic in here, I could say if context.currentUser, because this is you can always get the current user, the authenticated user by calling context.currentUser.something, something has subscription, et cetera, that I've implemented, then that would be how I do that here. I don't have that. So this is just going to always restrict. So where am I going to use that? So I can use that on an albums, on my albums query. I can say instead of giving it all to you, I only want it to be available for subscribers. And so here we go. Add the sublimiter directive onto the albums query. And now instead of getting all of the albums, of which there are about 100, I will expect this will be restricted to three. And so there we go. I can take certain bits of implementation and I can slice them in different ways and I can attach them via the SDL where that makes sense, which is really handy and can really clean up your code. Instead of putting all of that in the services file for every single thing and replicating it all over here, it is just in the SDL. And what's really great is I can copy that and I can say, well, I want that to be true also for popular albums. Guess what? You only get three. So I can put it on there and now I can say pop albums and we will expect that. Indeed, I'm still unauthenticated there because I didn't skip off. Remember? So I can just skip off and now that's a public query that I can make. And let's see if it worked over there too. Let's execute that. And here we go. Now I only have three albums that have been returned. And unfortunately, that's all the time I have today, but this goes much, much deeper. We make it easy to test each of these functions that you create because they're isolated. You can unit test them very easily with the tests that we generate for you here. We have advanced features like depth limiting to avoid people abusing your service, all of the secure by default functionality, logging integration, and even caching coming very soon. So if you like what you've seen and you want to learn more, go to redwoodjs.com. Check it out. Follow our project on Twitter at redwoodjs. And if you want some free stickers, which I know you do, go to redwoodjs.com and sign up for some free stickers. Thanks for listening. What do you think about these answers here? Is this what you expected? Well, let's see. I was hoping that a lot of people hadn't heard about Redwood so that they could now have heard about it and answer that they had in the future. So let's see, never heard about it. Yeah, 30%. I heard about it, never tried it out. That's actually amazing. I like to keep track of how much Redwood is in the public consciousness. Are we getting the word out? And so this is great. This is actually, I thought it might be lower than this. This is amazing. I mean, hearing about it is the first bit. Tried it out or using it on a project, 0%. Well, there's nowhere but up from there. We're a young project. So I think that this is, I mean, this is exactly where we want to be when it comes to this stuff. We want to be where people have heard about it and now they can go to the next step. Exactly. I think these are good stats. Some of them have never heard about it, so now they have, and now they can try it out and go from there for sure. Exactly. Awesome. Yeah. Let's go to the audience with some Q&A. Now remember audience, if you have any questions for Tom, go ahead and put those in the Andromeda Q&A and Discord and we'll answer those right now. We do have a couple of questions already here for you, Tom. First one is, is Redwood open source? Yes. Redwood is MIT licensed and free to use. So the sky's the limit. Use it for anything you want. Make it your own, change it. We love contributions, obviously. We have over 250 people who have contributed to the framework already. We've actually been working on it for several years. So it's become fairly mature, but it's still pre 1.0, though a 1.0 is coming very soon. We're in the release candidate phase now. And so we love contributions. That's why it's open source. I'm a big proponent of open source. It's helped me out a lot in my career and I've always enjoyed participating in open source. And so absolutely, MIT licensed, free to use. Awesome. Yeah, I love open source as well. What about the production capability? Is it ready for production use? Well, it's not quite 1.0. Like I said, we're in the release candidate phase now. We just entered that about a week and a half ago. And so it's quite stable. There are still some bug fixes that we'll do. We intend to be in release candidate phase probably until February or March of next year. So a couple of months as we work through bugs and just make sure that the first user experience is really top notch. We have an amazing tutorial that if you're interested in what you saw today, go to redwoodjs.com and breeze through the tutorial a little bit and you'll learn a lot more about not only the back end, but the front end as Redwood is a full stack web application framework. It's not just the graphql side that you saw today. It really has a full web application side as well. And so we work very hard on that. And we should in a couple of months be 1.0, which means I would say absolutely yes, use it in production. Though there are startups, funded startups today are building with Redwood and in production. So it can be done. Amazing. Awesome. Well, speaking of that, like you showed off a bunch of really cool stuff. You made it look so easy on the back end. What about the front end though? What is that like and what are the strengths with the front end? So Redwood is right now react based front end, and we do a lot of work to integrate the front end and the back end. So we have a feature that we call cells, which is a declarative way to do data fetching. So once you have your graphql back end on the front end, if you want to do data fetching to get data and then render a react component, use what's called a cell and you just say what your query is, and then you say what you want to happen, what component you want to be rendered when you're in a loading state, when you're in a failure state, when you have an empty result set returned, or when you have a successful return, you just list out what those components would be. Instead of having all kinds of conditionals that you have to wade through in your code base, it makes it a lot easier to manage and it allows us to get into the life cycle so that in the future we can do even more interesting things and optimize that data fetching flow. But that's one of many things that we do. We have pre-rendering capabilities. So in your routes file, you can just say you want a specific page to be pre-rendered, and then at build time, we'll pre-render that page so that it's statically available, which is great for seo and performance, and then it will be hydrated on the client and presented to the user. So, and this is just a few of the features that we have. You can go to the website, obviously, and check out everything that's there. The tutorial covers all this stuff really well. So if you're intrigued, definitely go through the tutorial. That's the number one thing that you should do if you want to learn more. Yeah, it sounds very interesting. And like, it sounds like it solves so many issues that, you know, other frameworks might have or they're trying to solve for as well. And speaking of that, what other full or how does Redwood compare to other full stack frameworks? And Metin specifically wants to know, are there any that you're afraid of? So we live in the same space as, I suppose, Next. Next JS, obviously very popular, is awesome. It's an amazing little framework. Now it doesn't bring much more to the table. Like there's a lot of things that work with it, but you're going to be doing most of the work yourself to integrate those things. And so compared to Next, Redwood integrates a huge suite of tooling, storybook is included by default. You don't have to set that up. It's fully integrated. Jest testing, integrated. graphql on the back end, integrated. All of these tools that you're going to eventually want to add if you're building a project or building a startup are already there with Redwood. So that's the biggest difference when it comes to something like Next. Now there's other frameworks that are more full stack being built as well today. Things like Blitz JS, which is built on top of Next, adds full stack back end capabilities. They also integrate prisma from the database side, but it's built in more of a Next context. So if you're into Next, that's one to check out. And then there's also remix, which has recently been open sourced and is taking a bit of a different stance there. Now, neither of these other two are leveraging graphql. So if you're watching this conference, I'm guessing that you're into graphql. And so if you want to use graphql as your transport protocol from your front end to your back end and make it easy to add additional clients as you go forward, a mobile client or a command line client or what have you, then Redwood is going to be super optimized exactly for that case. And a big reason to choose Redwood will be for graphql, which none of the competing ones will offer you. Nice. So you mentioned that the front end uses, or you said right now the front end uses react. Are there plans to maybe change that to something else or maybe incorporate other front ends like an astro type of thing? Yeah. So from the beginning, we've intended for Redwood to be a multi-client kind of an architecture, which is why we use graphql. One of the things that we can do in the future because of that is very easily add other client rendering technologies. So you could imagine that in addition to a react based front end website, we could have a view or a svelte based front end website that still just consumes the same graphql back end. And indeed you could use multiple of those if you had different sites that you wanted to deploy using different front end technologies over the ages, or really it's no different than having a react based, like a react native mobile app side, which we would love to add sometime. But once we get to 1.0, we'll start looking into what of these other technologies people are interested in us working on and making those things much easier to integrate with your graphql back end as well. So the sky's the limit when it comes to front end technologies. Yeah, no, that's amazing. Having so many different options. People love to have the options. So there's one more question here, back to the open source topic. Is there a plan for an earnings model since it's open source? How are you going to fund it? Well, right now I just fund it myself and there's a number of people working on it full time. I find myself in the lucky position to be able to do that. And I like that because I don't have to worry about any of the startup stuff that normally comes along with this. I don't have to worry about VCs trying to make things go faster than they should, or leverage or monetize things that are kind of unnatural. It's hard to say what the future holds for Redwood. Mostly I wanted this to exist to help people build their startups and projects more quickly. That's why I'm in this space to begin with. That's why I became a developer myself. And so being able to give back this way is really satisfying to me. Now I would love for there to be some kind of a Redwood membership someday where people could pay some fee to get access to the team more easily or to premium content or something so that I'm not having to foot the bill entirely myself forever, which would be nice. But I always want it to be done in a way that is additive and in a way that really embraces the community and pushes Redwood forward in an open source perspective and really is done for the benefit of the community. That's really important to me. That's the true nature of open source. That's amazing. I commend you at doing that. That's awesome. Well, that's all of the questions that we have from the audience. So I want to thank you, Tom. And we're going to invite anyone that has any more questions to go to spatial chat to Tom's speaker room. You can ask more questions there. But for now, I'm going to say thank you again, Tom. And then we're going to move on to our next topic. Thank you so much. All right. Thanks, everyone.