In this talk, we'll look at some of the modern options for building a full-stack React and GraphQL app with strong conventions and how this can be of enormous benefit to you and your team. We'll focus specifically on RedwoodJS, a full stack React framework that is often called 'Ruby on Rails for React'.
Rock Solid React and GraphQL Apps for People in a Hurry
GraphQL Galaxy 2022
Well, it's definitely been a minute since I started working with graphql. It's been about five years, in fact, and in technology years, that's quite a while. And when I was first starting out with graphql, I didn't really care how long it would take to work on a project or get a graphql app up and running. But these days, I find more and more that I'm in a hurry with my projects, and I want something that is faster to get going with and faster to maintain. And so that's what I'm going to talk to you about today, how to deal with react specifically and graphql if you are in a hurry. My name is Ryan, and I do a lot of things around the web. But one thing I'm very focused on today is course lift. And course lift is course hosting for people who want to have all of the mechanics of how to put together their course landing pages, how to put together their sales information, et cetera, done for them so that they can focus on making their course and we help them sell their course. Check it out at course lift on Twitter if you're interested. So going back to 2017, five years ago, when I started getting involved with graphql, it was an awesome time because there was just so much energy in the community around graphql. It was fairly new. I know that it dates back to 2012 at its inception. But it was around this time in 2017 that people started getting really excited about it. And that excitement was really palpable. This is me at graphql Summit in San Francisco. I got to do a talk there back in 2017. And there was just a ton of energy in the room about graphql. People wanted to put it everywhere. People wanted to use it in all their APIs, from all their front ends. You could really get that sense at the conference. And it was around this time that I started working on a large project for a brand new client. I had been working for Auth0 at the time, but I started to break out and go on my own doing consulting work. And I started to work on big projects that used graphql in this new case of this new project. And it was around this time that I was really getting my footing with graphql. I was trying to figure out how to work it into this project and how to make it really good for the client in particular. And what I noticed is that there were a lot of frustrations that came about as I started working on this project. And I could bucket these into a few different categories. And the first one is that it was kind of unclear to me at the time how to deal with different modules, how to separate parts of the api into different portions, how to deal with things like, okay, I want a user's module, and then I want to have a module for some other resource. How to bucket those things off and then bring them all together in a cohesive way just wasn't really clearly established. And so because there weren't these conventions in place, you were sort of left to figure those things out on your own. And so I came up with a convention that worked in my project, but it definitely was quite bespoke and maybe wasn't the best way to do things. This led, I think, to a lot of repetitive and manual work. I'd be copying and pasting module folders over, changing names, and then having to import things into a main file, put all that stuff up into a make executable schema in Node. And it was just this repetitive kind of manual task that I had to deal with. And at that time, also, there were no really good frontend abstractions for your frontend backend author time integration. I remember that it wasn't really all that clear how to get information when you're working on the frontend as to what the backend could offer up in terms of resources or fields on your resources. And so this integration between your frontend query clients and your backend schema, it just wasn't all that well established at that time how to make those things work well together. So what this led to really was a set of bespoke and brittle solutions. I put together things that I thought worked well in the application, and it turned out that these were a little bit brittle. So things like things breaking as I would add new modules, forgetting to import one of the new pieces of the schema into my main file where I make the executable schema, things like having to deal with file uploads and authentication, all these different pieces of the application that are fairly standard in most places just weren't all that standard in graphql at that time. Things have definitely gotten better over the years. Adoption has grown. More and more large companies are using graphql, and more developers everywhere are trying it out. I think nearly all the technical points of graphql have gotten better over the years. We've got better server libraries these days. We've got more of them, in fact. We've got better ways to arrange these conventions across our projects. tooling is better all around. We've got integrations from code editors, and we've got integrations between frontends and backends at author time now, which is great. We've got things like code generation, which helps to make modifications to our code in an easy way. And ultimately, type safety has really been a big benefit of all this. Being able to know the types that are available on the graphql api and then being able to use those across the application stack has been really beneficial for author time type safety. But I think there's still some room for improvements, and I think that's because new graphql developers, they're often left confused. I've talked to many graphql developers who just have a hard time understanding all the pieces at play when they're trying to get started. I think that's because the learning loop for graphql can be quite challenging. Needing to figure out what a schema is, what a resolver is, and how to interact with those two things from the client can be a bit challenging. This question of where does graphql fit in the stack can be one that is challenging as well. Some people think that you should put graphql between your server and your database, for example, whereas others think it's strictly from your client to your server. And so informing new developers on where graphql really should fit into your stack can be a challenge. How do you work with other APIs when you're dealing with graphql? How do you work with APIs that aren't built on graphql, trying to integrate those? And then what tools are needed to make the whole stack fit together? That can be a challenge for new developers as well. And so I think if we can get early wins, early wins in the sense of being able to figure out the clear benefits of graphql in a very quick way, I think that it's possible then to get developers more excited about graphql. And so if we want more graphql adoption, if we want more people to be trying it out and using it in their projects, I think that focusing on those early quick wins is a critical piece of it. So in my mind, there is an ideal experience and it kind of looks like this. We should have the benefits, the clear benefits of that client-server relationship be more easily seen at the outset without having to think about all the mechanics. So without having to think about, well, what's the definition exactly of a schema? What does a resolver mean? What is the client piece? What is that all about? Instead, being able to show the clear contract that exists between those things and being able to do so in a way where the developer doesn't need to think about all the internals and the mechanics. I think that is a very big win. Having a way to be able to handle other pieces that you would find in any other kind of environment, I think is important too. Things like authentication and authorization, file uploads, those sorts of things, being able to have a clear way to show how to do those things because they're necessities in most applications, I think that being able to demonstrate how to do those things early and easily is an important part. And then automatically be informed about the graphql schema across the stack. So getting type information from the graphql schema that exists, being able to use that type information to inform ourselves at author time and having an easy way to do that, I think is key. There are numerous ways that this is made easier these days. There are more and more frameworks, more and more kind of getting started packages out there that help with this sort of thing. But the one that I'll talk about today and the one that I think is probably the best way to bring this experience to life is a newer framework called Redwood.js. Redwood.js is this highly opinionated framework. It brings together lots of different pieces of tech into a very cohesive and very nice to use way. And one of the things that I love about it is it offers a lot of conventions and patterns that make it really easy to have consistency across an application, especially if you're working with multiple developers. And it's a very nice framework that brings together a lot of great tech that we'll touch on today. What does a Redwood app look like? Well, it brings together these items. We've got react, graphql, Node, prisma, storybook, and Jest. Those are the main pieces. There are some others as well. And it brings these technologies together in a way that is super cohesive and super easy to get started with and to go beyond with. We don't have to worry too much about these pieces. You know, as our application grows, they just keep working and they work very well. When it comes to a Redwood app, we've got two sides. Redwood apps exist in a monorepo, in a yarn workspace. We've got a website and we've got an api side. And so this monorepo approach is great because it allows us to work within a single project, but work on both the sides, the web and the api side. And so the question often is around Redwood, you know, what does it do? Does it just kind of like install a bunch of packages for us for those technologies? Does it just give us a package JSON and then we, you know, install all those individual pieces of tech? And the answer is no, it has a lot more than it does. It gives us a huge set of generators, which saves a ton of time generating code. We get scaffolding for things like being able to take a model and then be able to give ourselves the whole CRUD story around it. So all of this pieces of schema that we need, resolvers that we need, and then also all of the front end parts that we need as well to be able to do CRUD. We get authentication out of the box. So, you know, typically if you're working with authentication in graphql, you might be reaching for a custom directive. We get that stuff automatically with Redwood. We get routing solved for us with Redwood. We get a very nice implementation of a router within the react layer with Redwood. It's a very smart abstraction, works very well. We get things like layouts, you know, convention for having an application shell, for example, that can be used across the application. We get code mods. When it comes time to upgrade the Redwood version that you're on, oftentimes there's code that needs to be updated across the application, and we can just run a simple npx command to get that code updated across the whole app for us, which is great. We get to work within monorepos. It makes things much simpler when we're dealing with a single repo for the front end and back end of our application stack, rather than having multiple pieces that we have to worry about, you know, committed to different repos and deployed in different ways, et cetera. And then the thing I love most is just custom patterns that Redwood offers, things like cells, which we'll get into. Cells are this abstraction that gives us a way to handle the whole life cycle of a CRUD operation, and we're going to see that in some more detail. Generating components is very simple. We use a yarn command. So it's yarn Redwood generate components, and then whatever your component name is, for example. We get the same thing with a page. So whereas we would have a component that might just be an isolated bit of a UI that we might be working on, we might also want to have a page, which is kind of like a larger shell where our components go. And then we might want to generate a layout as well, which is going to be a kind of an application shell. You can think of it like that, which ultimately offers up something that looks like this, having our app shell with any number of pages that might be in it. And then those pages themselves would implement various components. And this is a pretty typical way that an application is laid out. You've got like maybe a nav bar and sidebar in your layout, and then you've got pages inside that can be navigated to, and then components that do the work of the application. Then if we're dealing with a server resource, something that would reside as a schema bit on our server with a resolver, we can target an SDL to be generated. So it'd be yarn Redwood generate an SDL, giving it a name, and then we would get a full graphql schema, a full set of resolvers, and we would be able to use it immediately with graphql calls. So, that's a lot of the theory. Why don't we see Redwood JS in action, and we can see how graphql really shines within a Redwood app. So when we're dealing with Redwood and we want to get started with a new project, we can do so with yarn. We can do yarn create Redwood app, and then give the app a name. Let's call this one graphql Galaxy. And then I'm going to say I want typescript. Basically this is what I always do. You know, typescript is what I use by default, but you can get Redwood in a standard JS flavor if you want as well. Just don't put on the dash dash typescript at the end. When we do that, we're going to get a new application started for us. It's going to install all sorts of dependencies. It's going to go through and put together all of the packages that are within a Redwood application. So react, graphql, we've got storybook, Jest, and more. And it's going to put all those things together for us into our new package. It's going to run yarn install, and it's going to generate types right off of the bat. So type generation is something that happens automatically within Redwood JS, and that's going to happen for us right here at the installation phase as well. So we'll give this just a minute to run, and then we'll hop into the project and see how to work with graphql in it. All right. We are all set here. So I'm going to CD into graphql Galaxy, and let's open this up in VS Code. And we'll give a really quick tour here of what's in the directories. So as I mentioned, we've got two sides. We've got a website and an api side. Here's our website, all of the stuff that goes into the client portion of our application. And then here's the api side, and this is where stuff like our database models reside with prisma, and it's also where we're going to manage our graphql pieces. So the first thing we might do is we might fire this up and take a look at what it looks like in the browser. For that, we can do yarn redwood, or if we want to, keep it short, rwdev. And when we do, we are going to have a new project over in the browser that we can look at. So this is the main splash page for Redwood. We don't have anything yet in terms of pages, but we can generate one, and let's do that right now. Let's go and generate a page. To do that, I'm going to open up a new terminal, and I'm going to do yarn redwood, or just rw for short, generate a page, and let's call this page our Galaxy page. And we'll see what this looks like over in the browser. When we generate the page, it goes into the web directory. If we go to source, into pages, there's our Galaxy page, and it's got things that we are interested in, like our react component that makes up the page, and also a test that comes along with it for free, and a storybook story as well that we can work on. Over here, our page is showing up. Let's navigate to it. Here is our Galaxy page. So for this page, maybe we want to have a Galaxy resource on our back end that we can work with. Maybe we want something in our database, a resource that we can do some crud operations against. For that, let's come over here, back over to the terminal, and we are now going to use something called a scaffold. But the first thing we have to do, actually, is set up our model. Let's come to the api directory, and we will go into our model, which is going to be under DB, schema.prisma. And what we'll do is we'll take out this example that comes with the Redwood installation, and we'll give ourselves a new model called Galaxy. So this is going to be like a table which will hold galaxies. So maybe the Milky Way, and Andromeda, and all the other ones that exist in the vast universe. Let's start by having an ID field here. We'll just make this an integer for now, and the default value can just be auto increments. So we'll auto increment that ID. We'll want to say that this is also the ID for this particular table. Might want a name. Name can be string. Might want a description, which will be string as well. And then typically we want to keep track of when a resource was created. So created at can be a field that is a date time type, and the default can be now. And then maybe updated at can be there as well. And we can track when updates happen. That's a date time field, and we can use the updated at decorator so that we can automatically get those values. So we have a galaxy table, and we are using, in this case, SQLite as our database. If we run installation on this, we should get everything wired up. So let's, I should say, if we run our generator for this, we should get everything wired up. So we can do yarn Redwood prisma DB push. That should give us our database. So there's our database, dev.db, and it's going to have that galaxy table in place now. And so what we can do to give ourselves a really easy way to work with data here is we can do yarn Redwood scaffold, rather generate scaffold galaxy. Let's run that command, and we'll see what we get. So we have got a layout. We've got routes. We've got all sorts of stuff. If we go to our routes file here, this is our routing file at the react level, we've got a whole bunch of new paths. We have got a path where we can add a new galaxy. We've got a path where we can edit an existing one, and all sorts of stuff that points to different components that have been created for us if we take a look within our web directory. So we've got a new page here, which is a galaxy page. I created an initial page called galaxy, which we could probably get rid of now since we have another dedicated resource called galaxy page. And then we've got a bunch of components that fit underneath this galaxy resource, which will give us all of the stuff we want to do for managing CRUD. If we look in the api directory, we've got a bunch of stuff as well. For example, galaxies.sdl. So this is the graphql schema on the server that we want for managing this resource. Now we can see that immediately it gives us what we might expect based on an initial kind of sampling of this model that's in the database. Taking the fields that are on this model, we can interpolate here that we might want to have ID, name, description, all of these things available as parameters on this object. We get queries for galaxies, plural, a single galaxy by its ID. We get the ability to do mutations right away. And if you notice here, we are requiring auth right away. So we've got this decorator require auth. If we don't want that, we can choose to skip auth, which is useful at develop time. But it's a very nice feature of Redwood that it automatically will give us authentication to protect our resources in case we forget, for example. So we've got everything in place here to give ourselves a full CRUD operation, set of CRUD operations. If we look in the services directory here in galaxies.ts, these are the accompanying resolvers that will be used to do all this CRUD. So why don't we take a look over in the browser again. If we refresh, there's nothing on the page here. And that's because we need to get ourselves to a spot where we can edit it. So if we go to galaxies slash new, here we go. We are able to add a new galaxy in Milky Way. Home let's call this home as a description. We'll save this. There's the record in our database. We can edit it to be something else. We can save that. We can delete it. We can show it. We've got all sorts of operations that are just given to us for free by Redwood by virtue of generating this scaffold. And the important part that I'll hone in on here is that all of the graphql parts are solved for us just by virtue of running that command. So for example, if we go to our components directory to galaxy, and then we go to galaxy cell, here is our graphql query that was generated. It asks for all of the fields back that we've got on that model. It sets up all of the states that we might be in for doing a CRUD operation. So what if there is a successful operation that happens, it sets us up for that. What if they're in a loading state? What if we're empty or there's a failure? It gives us those as well. And then the accompanying server pieces for this, like we already looked at, are already there just generated automatically. So when we're thinking about a way for developers to get started with graphql in a very low friction way, a very easy way where they can just start to see the benefits of graphql itself, I think that Redwood provides a very clear path for that. Things are generated automatically. We don't need to spend time figuring out exactly the syntax of the SDL piece that we might need, how to tie up a resolver to it, how to put the query piece in. It's just done for us automatically. And then we can spend time figuring out how all of these pieces operate together. But that very easy way to get started is done for us, which I think is a very big win. So if you're new to graphql yourself and you like what you've seen in terms of a clear getting started path for it, check out redwoodjs.com and it's as easy as we showed today. Or if you're an experienced graphql developer and someone you know is interested in graphql, I might recommend that you tell them about Redwood so that they can have that very easy getting started experience. Get the mechanics out of the way, get a very clear path to just getting the benefit first and then figure out the rest after. Thanks very much. My name is Ryan. And once again, I am the founder of CourseLift. If you're interested in course hosting that helps you market and sell your courses, check out courselift.com or courselift on Twitter. Thanks very much. Hey Ryan, welcome. Thank you so much for being here. Just a reminder to the attendees, you can ask your questions for Ryan on Discord and the Andromeda Q&A channel. So yeah, Ryan, let's go ahead and start by taking a look at the results from the poll question that you asked before your talk. So again, on Slido, we can take a look and see. It looks like most people have answered, about 50% have answered generate schema model. Closely behind is generate SDL model. So what do you think about those answers? I think people were on kind of the right track, but it looks like the correct one was voted lower than the incorrect one. It is SDL to get yourself a full set of CRUD resolvers of your SDL for your backend. So if you have some model in your prisma schema, you can do yarn redwood generate SDL and then your model name and then you get all that code generated for you. Awesome. Yeah, it sounds like a really great way to just get things rolling and give you everything that you need. So great. Awesome. Well, let's go ahead and start with some of the questions that we're seeing. The first is, how does Redwood differ from other frameworks and meta frameworks, things like Next or Blitz, etc. Yeah, so Redwood, it's an interesting kind of concept. It brings together various pieces of technology that are already established and are well known. So we saw in the talk react, graphql, things like Jest, things like storybook. It brings these all together and gives you a cohesive way to use them without much fuss. Because one of the most difficult parts, I think, about starting a project that you want to use all those pieces of technology in, you've got to wire them all together and you've got to follow docs to do all that. Redwood just solves that for you. I would say next.js, for example, much more focused on react. Of course, you can do api kind of things with Next, but Next doesn't have an opinion so much about how you would put graphql into the mix, for example. It surfaces a way for you to have a front end and a back end, but is less opinionated perhaps in that way. Still opinionated in the fact that it gives you kind of its own domain specific way of using react and using a back end, but brings together fewer of those tools. I would say Redwood is much more closely related to something like Blitz, where Blitz has similar goals. It gives you commands to run, to scaffold out an app for yourself. It gives you a way to tie it together, various pieces, very easily. So Redwood is kind of similar in that vein to Blitz, but with its own set of opinions, et cetera. And then if you look at other frameworks, I mean, maybe you call react itself a framework. Some people would say it is. Others say it's just a library, but it differs in that way because react is just for the user interface for the most part. And then same thing with frameworks like angular, for example. You would more so see Redwood doing all of the stuff across the full stack for you, whereas angular is just for the front end. So I think that's a little bit of how they differ. Yeah, it's interesting. I think if you look at frameworks, libraries, utilities, like APIs, and you think about a few vectors around, is this front end, back end, full stack? Is this opinionated versus non-opinionated? And is this more of a library versus a framework where it's going to be very directive in how you use it? Redwood seems to be an interesting overlap across those three vectors. If you want to get up and running very quickly, have it cover as much of the stack as possible, and then also have those guidelines in place for you to be able to make decisions that are in line with the best practices. It covers a lot of those use cases. And one thing that was important to Redwood at the outset is that it be targeted towards easily deploying to the jamstack sense, so deploying to serverless, where without really any fuss at all, you would deploy your graphql endpoints to a serverless function. You could deploy any kind of individual functions you might be wanting to work with as serverless functions as well. It's just super easy to work with serverless too. Yeah. And we're seeing from an architectural standpoint, teams that can work in that environment, they're able to move pretty quickly, which is great. Awesome. Another question is in line with that, actually. Which features of Redwood offer the most productivity gains? Yeah, for me, it's generators. Those are pretty huge. There's this argument to be made that generators might not be the most important thing for a framework, because once you've generated your code, you're then kind of maintaining components you've already built. And so you're not maybe always using generators. But for me, especially when starting a project, being able to scaffold things out and generate, get a whole bunch of code just done for you is huge. And I've started using, I got on the train with like chat, UBT giving me code now. I am using Copilot and stuff like that. So the more code that can be written for me, I'm all for it. I'm not a purist that says I've got to write all my own code. I will happily let the computer write the code for me. So Redwood is great for that, just generating code to get you out the door. And then you make the appropriate changes that you need, of course, to your components and build from there. So it's a huge boost. Awesome. And one last question we have time for. Is there any feature that's coming up that you're looking forward to? Well, there's talk now about kind of handling authentication in a bit of a different way. Redwood has been, their authentication model just quickly has been kind of strictly tied to a provider. You can use many different providers, but it's pretty well coupled to that provider that you might choose. And now there's work to be done to decouple authentication that has traditionally been coupled to a specific provider. So I'm looking forward to that. Awesome. Well, I can't wait to learn more about that. And so thank you so much, Ryan, for answering our questions and for your amazing talk. We really appreciate you being here. Absolutely. Happy to be here. Thanks for having me.