Exploring the WordPress Graph with Next.js & WPGraphQL


Headless Wordpress using its built-in REST API is a powerful solution to scale WordPress to the web, but complex relationships can easily turn into chains of requests, making maintainability difficult along with the potential cost of performance.

With WPGraphQL, we can harness the benefits of GraphQL, leading to a better developer experience and optimized request logic, making sure we’re only delivering what we need to our users.

We’ll explore these advantages and how these pieces fit together with modern tools like Next.js to build great experiences for the web.

Slides & more


Hey everybody, let's dig in and explore the wordpress graph. So who am I? I'm Colby Fayok. I'm the one hugging BB and Kyler Ren over there. I work with the dev community as a developer experience engineer over at Cloudinary. You can pretty much find me anywhere on the web by just Googling my name, as I'm the only one in the world. So let's start off by addressing the CMS in the room. It's 2021 and some developers would still cringe at the thought of using wordpress, but frankly, we're still living in a wordpress world. According to Build with Trends a little bit ago, if we look at the CMS distribution of the top 1 million sites, 37% of websites are using wordpress. That's a huge percentage. I'm sure it's going to have gone up by now and I'm not quite sure how accurate it is, but if you look at the number of detections on the built list site, it's over 960 million installs of wordpress. That's almost 1 billion. That's a staggering number. While we might not all want to use wordpress, it's realistically around to stay for the foreseeable future. But hold up, why am I even talking about wordpress? Well jumping back a bit, wordpress as we traditionally know it is an all-in-one CMS and website solution. It works server side to grab all the data from the database, render it to html and then send it over to the browser. But since 4.7, wordpress now supports a REST api. This means right out of the box, we actually can use wordpress headlessly. If you haven't heard of the term headless before, what does that actually mean? Well, with our traditional stack like wordpress, somebody will visit a page in the browser. The browser reaches out to the server, the server will do the work like make those requests to the database, render the html for the page and then send that response. If we're lucky, it'll return it cached. Finally, the browser will display that response to the person who's visiting that site. With a headless approach, that request to the server might be asynchronous on the client. In this particular example, the person would visit a page in their browser and immediately get a response straight from storage. Once that page loads inside of the browser, the browser will kick off another request to a server which can load all that dynamic content. But I would imagine you're probably wondering why would we want to make a client side request to wordpress for a CMS. And that's not necessarily the recommended approach. That's where static site generators and modern web frameworks come in. They do all the hard lifting before the page actually hits the browser. We can use front end frameworks to get all that data at compile time or with server side rendering, avoiding that cost inside of the browser. Now if this all sounds new to you, it might sound like a lot of work. Why not even bother with an api? Why not use wordpress out of the box like we always do? So let's focus on this example of using an api with a static site where the only time we reach out to that api is at compile time and we store the html files directly in storage. We get a lot of benefits from actually avoiding hitting the server directly on each of those requests. With most of our server based solutions like wordpress, there's a lot of options to help speed things up. For wordpress specifically, that includes some plugins to cache or some custom work under the hood. But each page is still a server hit, which is still prone to its ups and downs. On the other hand, with our statically compiled site, a static html file is just going to be fast. Instead of spending time rendering on a server, you serve a static file straight from storage or CDN. While you can do this by default with wordpress, it's often much more complicated. And some of the plugins that cache might serve an html file, but they still serve it from a regular server, not static storage. With any server, we're typically paying for how much we actually expect our traffic to be. While most of the time that is predictable, we all hope to one day have a viral post. And if that happens, the people visiting our site will be the ones paying for it with slow speeds or timeouts. There are solutions like load balancing and auto scaling, but those aren't perfect solutions, and we might not always be able to handle that surge in traffic. Back to the fact that we're serving static html files, because we're serving files straight from storage, or better yet, statically from the CDN, buzzword alert, that means our user-facing website is going to infinitely scale. That static site will survive the Reddit hug of death when your post goes viral. But managing servers isn't always cheap. While a low traffic personal blog could maybe manage a few to be a few dollars a month, the more that traffic grows, the more that cost is going to grow. While you do still have those options like load balancing and auto scaling, those services add up really quickly. And without it, you again risk your site slowing down or worse, downtime. But storage is cheap. It's really cheap. We can maintain huge static projects in aws using S3 for a really low cost. But even if we still manage a server, the usage is going to be much, much lower because we're only having to deal with content managers or requests at compile time. Now I hopefully convinced you as to why headless is a good thing. Or at least set up some context about what's actually coming next. So how would I apply this to wordpress? Well back to the REST api, if I want to start building out my new static blog, I'll ultimately need to fetch all of my data. I'll start off by going to WPJSON, which is going to be some basic info about my website, along with a list of routes showing what endpoints are actually available to hit. Next I want to add my blog posts so I can hit the post endpoint and easily get them all. I can then simply load them up inside of my application and iterate through all of them inside of the UI. But I want to add more details to this. I want to know, for instance, who the author is. So I find the author ID in the post and it probably doesn't make sense to hit each, every individual author one by one because that could be a lot of authors. So I hit the author's endpoint and I try to match up the data. But now I also want to show some categories in that page. So again, I find the IDs, but this time for the categories and I request all categories and again, match up the data. Looking back at what I just did, though, I just made four separate requests to get the data that I needed for the page. Luckily in my example, I'm statically compiling so that might not necessarily end up costing the user, but that will certainly make development a bit slower. On top of that added complexity of managing all of that data and filtering it down so that I don't actually pass all of that data as giant arrays as props into the actual page, along with generally the extra strain on the wordpress instance for all those requests. Now this isn't meant to shame the wordpress api, nor is it meant to say that REST is inherently bad, but we're dealing with complex relationships in our data. We don't want to be limited by individual endpoints, leaving us with long chains of requests and more data than we actually need. We want to be able to provide the best experience we can. Now this is graphql Galaxy, so I think you probably know where I'm getting at here, but we can seriously level up the way that we're interfacing with our wordpress data by using graphql. And to do that, thanks to Jason Ball, who created the wonderful WPGraphQL, along with all the other hardworking contributors, we can add the power of graphql to wordpress. We can do this by simply installing it as a plugin right inside of our dashboard, giving us the ability to query our wordpress data with graphql. So before, I was talking about how I didn't like the idea of having to make all these four requests all chained together. So instead, we can load up our graphql client like apollo, and we can make a single request with our query. Instead of having to manage four full dumps of data, where we need to match everything up and have complicated logic and actually avoid bloating the application, I can query for only the data that I need, with all my relationships already intact, meaning there's less data that I have to manage and far less complexity. Now again, I'm going to do this during compile time, but we can see the realistic impact of what those requests would look like by making the request inside of the browser. While those KBs and milliseconds might not seem like a lot, it really does add up, and it becomes more noticeable inside the rendering experience. Not to mention, I don't have a lot of posts on the endpoints that I'm actually hitting here, so imagine a huge site that has a ton of posts. Also that was on my fast files connection. It's a little bit different when we see what that looks like when throttling with something like fast 3G connection. The post endpoint with my small amount of posts still took three seconds, so it really starts to become a huge difference. Now ultimately, we want to pull this into our application. We want to build that beautiful wordpress blog. So this is where next.js comes in. Like I mentioned earlier, WPGraphQL is a wordpress plugin install away. Once that's installed, you immediately have access to all of your data. The cool thing is with graphql, the graphical explorer is that it's installed by default with WPGraphQL, and it lets you interactively explore all of your data. You're able to click through and see everything that you're actually able to query right inside of that dashboard. As you're doing that in the middle column, it's actually building the exact query that you need for your app. And I've done just that with creating what I call the next.js wordpress starter, which lets anybody spin up a wordpress site with next.js super easily. Like you typically expect from a wordpress blog, the homepage is full of the most recent posts. I take advantage of get static props, where I request all those posts at compile time. That gets injected into the page, and I can build out my page exactly how I want with all of the pagination. Now of course, I want to make sure that we have all of the routes for our posts. So we can take advantage of get static paths, which is how we can tell next.js exactly what paths or pages that we want to make sure gets built. And once we define those paths, we can then look up the data, again, using get static props with each of those parameters. I would imagine someone would typically expect search as well, and the wordpress api provides search capabilities, but like I mentioned earlier, I'm trying to statically compile this. So then we would still be hitting the server, which I don't want to do here. So I took advantage of next.js sitting on top of webpack, and I created a webpack compiler that fetched all the posts at compile time. It would then create a search index, a static one, with titles and paths right inside of that static file. It then loads that into memory, or it loads it asynchronously on the client, and we can make sure our search is right to that index. The nice thing is we can couple this with all of our wordpress plugins that we are used to, like Yoast and ACF, where this gives us a lot of flexibility for how we actually manage our content and data. And these all work perfectly with WPGraphQL. So you're still querying all those data relationships with that one endpoint with everything right intact. So I know you all don't want to just see some screenshots of some code, so let's do a really quick walkthrough. So here's what we're going to do. We're going to first jump into an existing wordpress instance. I'm going to show you how we can simply install WPGraphQL. We'll then open up the Graphical Explorer so we can just kind of poke around and query our data a little bit. And then finally, we're going to create a new application using an example starter that I created, where we can see some existing requests and maybe tweak those requests just to see how we can pull in new data. So let's dive in. All right, so we're going to get started with pretty much a fresh new wordpress instance I have from WP Engine, where I have a little bit of preloaded content in here, including some posts and some pages, just so that we have something to actually query here. But really, the point is that I'm trying to make is that there's really nothing special going on in here yet. And we can even see under the plugins that we don't have any plugins installed. But our goal is to ultimately actually query all this post data with graphql. So what we want to do is we want to install that WPGraphQL plugin to actually be able to do that. So the first thing I'm going to do is I'm going to click Add New under Plugins. And I'm going to go to Search, and I'm going to search for WPGraphQL, which we can see that I've done before. And as soon as I make that search, we can see that right now in the first slot is that WPGraphQL plugin that I'm going to install. And then as soon as it's done, I'm going to activate it. And we can see as soon as it's activated, over in the left sidebar here, I now have this graphql tab. And I can even click this Graphical IDE page, where it's going to load up. And we can see that we have this Graphical Editor. Now, as I talked about earlier in my talk, we have the ability to actually real-time go through all of our data using this Query Editor. That way we can both see all the data that we have available, but we can build our query so that we can later use it inside of our application. Now to see how this works, let's try to check out what our posts look like. So if I scroll down inside of this Explorer panel, we can see that I have my post right here. Or if I start to open that up, we can then see in the middle column that it's starting to build that query in real-time. Now let's add some data to that. Where if I start opening up the edges and the node for those edges, we can now see all the attributes that I actually have for each of those posts. Where let's grab some things that make sense, like the date, and we have our ID for each of the posts. And how about our title for the post, where now if we click play, we can see that in this far right column, I now have all that data for each of my posts. We can see exactly what we showed over in this post page, but we now are able to query that with our WPGraphQL via graphql plugin. So now let's actually try to see how we can take this data and use it to build an application. So what we're going to do to do that is, because the next.js wordpress starter that I actually created is probably a little bit too complex for trying to walk through in this demo, I have this simpler example starter where really it's just a basic demo of adding some posts. So we're going to add a post to the page, that way we can see what it looks like to actually query the data in real time, and we can even tweak that query so that we can see what it's like to actually build the query, modify the query, and actually update it. So if we scroll down on this page, we can see the instructions for how we can get started with this, which is actually going to be similar to the next.js wordpress starter, where we're going to copy this yarn create command, where we're going to use create next app in order to do so. So if I head to my terminal and I actually paste in that query, and let's call this application my graphql Galaxy, and what this is going to do if you're not familiar with create next app is it's going to first basically clone down this example project that I have here, it's going to then install all the dependencies, and it's even going to reset the git history. Basically it's going to get us immediately ready to get started and get productive with our application. So now we can see that it's done, I'm going to go ahead and cd into that directory, and we can see that we actually have one more step before we try to spin up this page, where we need to add an environment variable, and this is going to be our graphql endpoint for our wordpress instance. So as we can see, next.js convention, we're going to add this.env.local file. So I'm going to first open up my code editor with my new project, and at the root of the project, I'm going to create a new file called.env.local, and inside here I'm going to add that environment variable. Now over back on the instructions, I'm going to copy and paste that right inside, and next we don't want to try to query your host.com, we want to actually query our wordpress graphql endpoint. And that endpoint is going to, by default, be basically wherever your wordpress instance is installed, slash graphql. So for instance, if I open up my spacejellydemo.wpengine.com slash graphql, we can see that while I do get an error here, we are able to see that this is a working graphql endpoint. So I'm going to take this same URL, and I'm going to paste it right into my environment variable, where we can see we now have this wordpress graphql endpoint set to my actual URL, and now let's try to spin up our development server by running yarn dev, and we can see that immediately it's going to spin up a new server pointed at localhost port 3000. And if I actually try to open that up inside of my browser, we can see that next.js is going to start to compile that page, where basically it's pulling down that information for us, and it's going to actually build that page in real time. So we can see here now that I have my new blog post, my blog page that is, my blog website, and we can see that if we start to scroll down here, we have all those posts that we saw right inside of wordpress, but now we're actually getting them inside of the application inside of our browser. So now we can see that we have each of the title, and we have the description, and we even have a link for each of our posts, but we want to add a little bit more context to this. How about, what if we want to add the author to each of these posts? First, let's dive into the code to see how this is actually happening. So I'm going to go back to my code editor, and I'm going to particularly go to source pages index.js, which is going to be our homepage. And if we see at the top here, if you're already familiar with react, there's really nothing special going on here. Really we have our home component that's taking two props, and it's rendering that out into the page. But what is special is if we scroll way past that react component, we have this function that we're exporting called getStaticProps, which is the next.js way to fetch data that's going to be static for our application at compile time, where we can see that we're getting our apollo client, and we're building this graphql query where we're grabbing some general settings for our website, but we're also grabbing all those posts, just like we saw that we did before inside the graphical editor. Finally, once we have that data, we're going to just clean it up a little bit, and we're also going to construct the path that each of the posts is going to be available at. And then we're going to simply pass them as props, which again, if we scroll back to the top of the page, we can see that page and post props that we're passing right to the react component. And then at that point, it's just like any other react component, where we're grabbing those posts, we're iterating through, and we're able to render each one of those inside of the DOM, where then we have our Space Jelly demo blog site. So now, like I said, we want to add that author to it. So I'm going to first grab that existing graphql query that we saw right here, the one that we're actively using inside this project, and I'm going to go ahead and paste it right in to my graphical editor here. I'm going to click Printify here, just to fix the indenting, but I'm going to click play, and we can see this is exactly the data that we're getting and passing into the application. We see that we have all the posts, we even get the excerpt here, but we also get that title and description, which we can see at the top that we're showing. So now, while we have all this other information for our posts, we want to also add the author to it. So we're going to find that post section, which is right here, we have our posts, and for each of those edges in the node, we also want to add the author. So I'm going to simply start to open up that author, query the node for each of those authors, and we can see we get all the attributes for the actual author on the post. Or in this instance, we probably want to grab the ID, since that's something that we usually want to have for each of our nodes, but then we want to also grab the name, which if we click play now, and I start to scroll down on the received data, we can see that we now see the author for each of these posts, which in this particular instance, it's myself. We see Colby Fayok here, but we were able to see how easy it was to paste in our existing query, update it, where now just as easily as we pasted it in, let's copy this, and let's paste it right back into our application. We're now going to fix the indentation there. We just updated the query inside of our app, and to see that this is actually working, I'm going to console log out the actual posts prop here, where if we go inside our browser, I'm going to refresh the page, and I misspelled that there, so instead of console logs, there's only one of them, but we can see when the page actually reloads and recompiles. We have this array of data, which is all of our posts, but we now have this author property here, where if I start to expand everything, we can then see my name, Colby Fayok. Let's actually add this into our page. I'm going to head down inside this react component, where how about right under the title, let's add a new paragraph tag, and let's say bye, and we're going to add our username. Let me close this paragraph tag, but we're going to specify the post.author.node.name, and just for my sanity purpose, the node author node name. Let's see if that works. Now, if we reload the page, and it actually probably should have fast reloaded, we can see that I do have Bye Colby Fayok there. Of course, the spacing probably isn't the best. We can fix the styling later, but we could see how easy it was to update our query, simply add a little bit of data to that by updating that graphql query, and we were able to immediately have that available on that post prop that we just passed right into the application. We were able to do that because we now have the power to query those complex relationships, even the categories if we want, by using graphql and wordpress. All right. Let's actually recap what we achieved here. We first took an existing wordpress instance, and we installed WPGraphQL. Once that was ready, we were able to see how easily we can query all that wordpress data with graphql. Finally, we bootstrapped a new application that takes advantage of querying with graphql, and then we added some extra info on top and with the UI. Now the goal here wasn't to get everybody, all of you, over to jump ship to wordpress, but it's to show the flexibility of it and why it's still a compelling option for a data management solution when coupled with graphql. We can come up with some pretty powerful solutions that provide a great experience for both our users and our developers. If you want to check out my work, next.js wordpress Starter is completely open source on my GitHub. If you want to learn how to actually do all this in practice, you can check out my course, e-commerce on the jamstack, over on Level Up Tutorials. That's it. If you want to learn more or chat about the talk, you can find me everywhere at Colby Fayok. I'll also tweet out some of the stuff you've seen here today. Thanks, everybody. We will start first with the question which you asked, and we will see how the people voted on that question. Just to recap, the question was, does wordpress work with modern development architectures? It's amazing if you see the results. It's like 100% yes. Everyone voted for yes. Did you expect that? I guess that question was a bit obvious. No, I did not expect that. I think for the most part, it does work with every site. But there's the plugins, for instance. Not every plugin is going to be supported, especially if you're doing very custom work with wordpress. But generally speaking, most of the wordpress sites are going to work pretty well with WPGraphQL. This is nice, because this is something which even I did not know much about. For me, I started in the era when the CMS, when the era was of headless CMS. So I didn't really know much about wordpress. So I definitely learned a lot. So I have a few questions for you. And the first one is, does graphql support the wordpress blocks? Yeah, so that's an interesting one. Because mainly that's what their newer editor is using right now. And unfortunately, it doesn't natively support it at the moment. And it's because the way that Gutenberg's created is it doesn't save the content inside of the wordpress database as traditional wordpress content would. But there is a plugin that kind of my understanding Hackly does that where it'll kind of scrape the content, I guess. I'm not too familiar with it. I haven't used it. But I know that there's some kind of solution around that. But generally speaking, most of the time, you'll use just the html string that's rendered from wordpress. Okay, so we have found a hack for like almost everything. There's always a way. So if you're determined, there's always a way. Okay, so I just wanted to know, like, you talked about WP graphql. So I mean, will it like work with any sort of wordpress website? Yeah, so generally speaking, yeah. The tricky thing is like, sometimes there's a lot of custom work that you can do with wordpress, right? Because of like, just the nature of wordpress is it's developer friendly, where you can do a lot of different things and customize it to exactly your needs. And a lot of those custom things, well, not I won't, I shouldn't say a lot of those custom things. Some of those custom things might not work out of the box with it, right? But that said, because of how WP graphql is kind of hooked into the core of the wordpress database, a lot of that stuff should kind of just work, including a lot of the plugins that you might be familiar with already, like advanced custom fields or custom post type, those kinds of things. That's interesting. I mean, definitely. So we have talked, like, we are talking a lot about graphql and all. So and like previously, and now also, we use REST api also in some of our projects. So I wanted to know your perspective on like, what do you think about like, from perspective, performance side? So you talked about performance in the talk. So like, how do you, what do you think about the performance? Like when thinking from using graphql APIs while thinking REST or while using the REST APIs? Yeah. So, and I think there's a little bit of a caveat, like with my answer, because every situation is different. But I think it really, some of the benefits of being able to use graphql is first of all, you're able to select just the info that you need, which really reduces in some instances where some REST APIs just give you a dump of all the data. And if you're getting that, those are extra bytes that that person has to download in the browser. But also in addition to that, if you're making additional REST requests, kind of like I showed in the talk, those network requests are going to add up as well. Right? Whereas that single graphql request is going to just make that one round trip. But again, like it always, it's always really dependent, right? Because if you're just making one simple REST api request, and that REST api already is giving you limited data, like, of course, it might be faster than that graphql query in your particular scenario. So it's really important to always test those things and try to make sure that you're really getting the best solution for you. But graphql generally is just so flexible in its nature. It's such a great tool to be able to use for data relationships. Yeah, that's amazing. You know, in fact, when we started today, the conference, we asked the audience that what do they like most about graphql? And their answer was definitely most of the people voted for be the, so getting the ability to pick what you want to get from it. Like don't get the whole dump of data, but you just get what you want, what you're requesting for. So that is definitely a great point. And yeah, it always depends upon the scenario. performance is subjective, and it will always definitely depend upon the scenarios. So thank you so much, Colby. It's been such a pleasure to talk to you and learn from you. It was such an amazing talk. I really learned a lot of new things, and I'm sure audience have enjoyed a lot. So now we are going into break, but before that, don't forget to join Colby on the speaker room, so in the special chat. Thanks a lot, Colby. It was really great to have you with us. Yeah, thank you so much to you and Git Nation. I appreciate it. I had a great time. Thank you. Thank you. Thanks for having me.
23 min
09 Dec, 2021

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic