547: WordPress and GraphQL with Jason Bahl
Jason Bahl joins the show to talk about the GraphQL and WordPress connection, his work on WP GraphQL plugin, Faust and Atlas from WP Engine, Jamstack and Wordpress, and more.
Time Jump Links
- 00:42 Guest introduction
- 04:02 WordPress is amazing - why reinvent it?
- 06:05 What's the origin story of WP GraphQL?
- 14:28 How did you end up at WP Engine?
- 17:27 Caching issues with WordPress
- 25:57 How do plugins like Advanced Custom Fields work?
- 27:08 How does it support GraphQL types?
- 32:59 What's the process of setting up WP Graph QL?
- 37:47 Can you subscribe?
- 41:09 How do you get involved with WordPress?
- 46:07 WP CLI
- 51:40 Jamstack plus WordPress?
- 54:36 What is Faust?
Transcript
[Banjo music]
MANTRA: Just Build Websites!
Dave Rupert: Hey there, Shop-o-maniacs. We're blasting off into 2023 with a brand new episode of the ShopTalk Show, a podcast all about websites. I'm Dave Rupert. With me is Chris Coyier. Hey, Chris. How are you?
Chris Coyier: Hey! I'm doing absolutely great. We're going to kick off this new year with a special guest that we have been working on lining up since last year. It's Jason Bahl. Did I say it right, Jason Bahl?
Jason Bahl: Yeah, that's correct.
Chris: Hey! How ya doin', Jason? Thanks for coming on.
Jason: I'm doing good. Yeah. Thanks for having me.
Chris: Yeah. Right on. I can't remember the exact impetus of all this, but it was kind of like I think I had noticed that there's this app I used to run WordPress locally called Local by Flywheel, or I think they just call it Local now because I think WP Engine purchased Flywheel.
I think Flywheel still exists as a brand, but perhaps they're trying to downplay the "by Flywheel" all the time now that WP Engine owns them. I don't know what the story is there.
But I notice this app, which I just feel like is a ten out of ten app. Really, they hit it out of the park, especially as far as I think business is concerned. If you help people solve a hard problem locally and give it away for free, and then say, "Oh, we have hosting to help you, too," God, what a homerun idea.
This app, it runs cross-platform. You download it, click a few buttons, and all of a sudden, you're running WordPress, which isn't the world's easiest thing to do. You've got to run MySQL. You've got to run PHP. You need a web server. There are all these things. And doing that without anything to help you has some technological challenges that even I'm... I'm sure I could get past them, but I would be annoyed by them. Then if you had five sites, that's just going to get even more annoying.
Anyway, it helps you do that, but it has plugins, too. One of the plugins is it'll help you optimize your images and stuff. It just has little bonus stuff that isn't built into the core of the app.
I noticed that it had this plugin. I think it's called Atlas or something. I think that's the code name for WP Engine's overall thing that helps you run what I guess the industry has been calling headless WordPress - or something.
The idea is I want to manage my content in WordPress, but I want to build the front-end of the site in another way. I don't want to use the PHP templates and stuff. I want to use - I don't know - Next.js or Astro of VuePress or whatever. Nuxt 3. [Laughter] Easy.
Dave: Hmm... [Laughter]
Chris: I want to do something like that. Yeah. [Laughter] Dave loves Nuxt 3.
Dave: One day.
Chris: Okay, so I know I've been talking a whole bunch, but there was a button in this thing. You click it, and it does all this stuff that it needs to do to not only let WordPress run but to scaffold out for you a website that allows you to do this thing.
One of the things that it has to do then is not just it has to run a node server, for example, to do the front-end. But the way that it's built is in a way a lot of modern websites are built that need to hit an endpoint to get some data is it's GraphQL powered.
Well, guess what WordPress doesn't provide out of the box is a GraphQL API. Now, should it or shouldn't it? I'm sure Jason has opinions about that.
Jason, you are the creator of a widely used plugin called WP GraphQL that brings GraphQL to the WordPress land. How much of that did I get right? [Laughter]
Jason: Yeah. That sounds pretty accurate to me. Yep.
Chris: [Laughter] Yeah. Right on. You are the creator. Still the maintainer of WP GraphQL, right?
Jason: Correct, yeah.
Chris: Yeah, and it's just a free thing. Anybody can install it, right?
Jason: Yes. Yeah, it's a free plugin. I've been working on it for six-ish years now.
Chris: [Laughter] Pretty intimately involved with it, I'd say.
Jason: Yeah.
Dave: WordPress is perfect. Why reinvent the horse here?
[Laughter]
Dave: That's the old saying, reinvent the horse. Why push the limits here?
Jason: Yeah. WordPress is pretty good, right? Forty-three (or whatever) percent of the Web is powered by WordPress right now, so it does a pretty good job already.
There are limits, I think, to the developer experience of rendering templates in PHP. And with the evolution of modern JavaScript frameworks, I think the developer experience has improved.
Component-based architectures and things like that allow developers to do things faster, share components across projects easier, things like that that weren't necessarily easy to do when you're templating in PHP.
Then obviously, PHP is a server-only language, so any dynamic interactivity or whatever you need, you have to also bring JavaScript in. And so, you're now templating in two languages, maybe three because you have CSS to go with it, too.
Being able to template in JavaScript, you can do a lot of this stuff to render the content but then also add the interactivity, you know, page transitions, things like that without having to cobble together PHP for templating and, like, jQuery or whatever you might be doing to have that interactivity.
I think the developer experience is what's pushing it toward folks want to enable businesses to manage their content in WordPress but enable developers to use whatever they're comfortable with to build the front-end.
That's where WP GraphQL comes in. It separates the data that you manage in WordPress and lets businesses keep publishing how they were publishing (unless developers choose whatever they're comfortable with).
Chris: Was that the original idea, too? That sounds so clean. [Laughter] That's exactly why this thing should exist.
Jason: Yeah.
Chris: What was that first commit like? Was that the story in your head?
Jason: No, so the origin story is a little bit different. I worked at a newspaper publisher. We had like 100-and-something newspapers across the U.S.
When I joined, none of the sites were on WordPress. I worked there about 3.5, 4 years. By the time I left, there were like 54 sites on WordPress.
And one of the things we needed to do was syndicate a lot of data, so we had, for example, Denver Post. I'm in Denver, and Denver Post was one of the papers we ran. Then we also had twincities.com in Minnesota.
Let's say the Denver Broncos win the Super Bowl. Well, Minnesota doesn't want to have a team out here covering the Super Bowl - or whatever - so they could subscribe to posts, to articles or categories from the Denver Post. When something was published by the Denver Post, if they were subscribed to it, we needed to publish it on their site as well.
They're independent sites, so it wasn't like a WordPress multisite or anything. They're independently ran sites.
Chris: Mm-hmm.
Jason: But they needed to communicate with each other, so we had the syndication platform - or whatever you want to call it - where data could be sent to all these different papers within the network and published.
And we were using the WP REST API before it was even in WordPress core. But we ran into a lot of problems with that from the actual performance time of it, like how long it was taking for data to be processed.
But maybe even more importantly, the developer experience around it because, with the REST API, it was like, to syndicate one news post or news article or whatever, it's a lot of different things. Right? A REST API is resource-based, and one blog post is many resources. It's the blog post itself, but then it's the images that are associated with it, which are each individual resources. Then it's the categories and the tags and the author and the author's image. It's all these different resources.
Chris: Mm-hmm.
Jason: And so, to syndicate using Restful APIs, it was a lot of spaghetti of, "Okay. We've got to move the post. Then we get reference IDs for the categories. Then we've got to go back and get the categories. Then we've got to move those. Then we've got to go back and get this extra data."
The developer experience around it was not fun.
Chris: Mm-hmm.
Jason: The performance, because you're waiting for one request to finish before you can do the follow-up request to get all the data you need, it was taking a long time. And so, as we started to scale, first it was like syndicating the 2 sites, and then 3, and then 54 sites.
It's like, man, to syndicate one post across the network was taking 15 minutes sometimes, and so I was digging into how we could fix this. I came across a technology called GraphQL, which at the time was pretty new.
We were working on this problem in 2016. GraphQL was open source by Facebook in 2015, so it was very new technology at the time.
I said, "Hey, this looks like it might help us with our problem. We can explicitly ask for the exact data that we want and do it in one request instead of having to do these follow-up requests.
Then on the mutation side, the writing data back to WordPress, we could do the same thing. We could write specific inputs that we can pass multiple things to -- posts, images, and whatever we needed to -- in one request as well. And we could be very explicit about it.
The GraphQL REST APIs are implicit. You hit an endpoint for posts, for example, and you're surprised with what you get back.
If you go to any WordPress site out there and hit their post endpoint, there's a very good chance they look very different. Right? You as the developer hitting the endpoint, you don't know what to expect. Right?
Chris: Hmm...
Jason: We had many people working on the newspaper, and if a plugin were activated or different code was added, your payloads might look different and, all of a sudden, there are bugs and you've got to track it down and things like that.
With GraphQL, I'm not saying it's bug-free by any means, but when there are bugs, you can identify it a little bit easier because it's very explicit. You said, "Hey, this is the exact data I needed." I can expect exactly that data where REST is like ... posts, who knows what I'm going to get.
Chris: Yeah.
Jason: Yeah, it helped us quite a bit with that. It's PHP to PHP. There wasn't JavaScript front-end in the beginning.
Chris: Interesting. Okay.
Jason: I was doing a lot of stuff in React at the time, and so I was like, "Hey, this makes sense for JavaScript." Obviously, GraphQL was created for Facebook to use with React as well, so I knew there was opportunity, so I started working on it as a community project. The newspaper was on board with that. They said, "Yeah, we'll use it, and you can do it as a community project," so I worked a lot on it on my own time as well.
Chris: Okay. Interesting. It was PHP to PHP at first because it solved actual, real specific problems. That makes perfect sense to me. That's awesome.
Then how long until--? Was it a plugin from day one? How long until the day of open sourcing? Years?
Jason: Yep. I mean I worked on it open source from the beginning. Even when we started using it at the newspaper, it was an open-source GitHub repo from the very beginning.
Chris: Nice! Well done.
Jason: From when we went to production at the newspaper, it was probably around a year-ish. Maybe not quite a year.
Chris: Yeah. Now you're gone, so do they still use it, you think?
Jason: They do. They do still use it. Yeah.
Chris: Nice. Your legacy lives on at the newspaper. Yeah, cool. Okay, so then you use it. But the opportunity for GraphQL is - I don't know.
You and I and everybody else, I think, thinks of it as this opportunity for JavaScript frameworks to talk to it. There's just some natural synchronicity there between how those things work.
By virtue of you open sourcing it has then opened the door for all these people who just prefer that DX, or that's the only world that they know. [Laughter]
Jason: Yeah.
Chris: I think there's an awful lot of developers out there that are like, "You know how you build websites? It's React. That's literally the one technology I know," or whatever.
Might feel the same way about GraphQL. They don't even know REST because GraphQL got so dominant in that world.
Jason: Yeah.
Chris: That they wire it all up. You know. No shade. I kind of get it, in a way, that I prefer that because I have some WordPress sites that are just done the classic way, just templated in PHP.
The fact that there's not even Prettier for PHP is so obnoxious to me. You're building a component in a modern JavaScript framework where any sloppy code I write just gets immediately fixed. My HTML looks beautiful and perfect at all times.
Then I come back to PHP land, and I'm like, "Oh, man. I have to manually indent this stuff? Get out of here." Just that little thing alone, that little piece of DX is so crucial to me that I get it.
I'm sick of building websites in PHP. I'd rather do it some other way. And this has kind of opened that door.
I say that and I've never done it. [Laughter] But stuff like Atlas makes me want to do it.
Now let's say we fast-forward really far. How did you end up at WP Engine, and how are they embracing all of this?
Jason: Yeah, so after a few years of working on the plugin, I joined Gatsby, which is the - whatever - JavaScript framework.
Chris: Mm-hmm.
Jason: And so, I worked there. They have a GraphQL layer themselves, and it sources from all sorts of different places. You have source plugins that can install.
Chris: Mm-hmm.
Jason: So, you can get data from WordPress (as one of them). But you could get data from Google Sheets if you wanted to, or Drupal, or Contentful, or whatever. Anything that can provide data, you can pretty much hook up to Gatsby and get data and then build the React site with it.
WordPress, they saw it as an opportunity, so I joined them. They paid me and a couple of other people to maintain open-source projects.
We had me working on WP GraphQL, and then there was Ricky was working on Graphical, the IDE for GraphQL.
Chris: Oh, yeah.
Jason: With John Otander worked on MDX, which is Markdown JSX mixed.
Chris: Yeah. Yeah.
Jason: We had a bunch of open-source maintainers that were working on different projects that were not part of Gatsby but Gatsby could benefit from. I worked there for a bit, and then they were kind of changing priorities around, and I was going to get pivoted to work on not WordPress stuff, and so I looked around. And WP Engine was like, "Hey, we find this interesting and important for our user base as well," so I joined them and am able to continue to working on the project full-time. I've been here about two years now. In about a month, I'll be there two years.
Chris: Well, aren't you a lucky guy? You also get to just work on WP GraphQL there too, or do you have to work on their kind of business initiatives?
Jason: Yeah. Yeah. I mean everything I work on is GraphQL centered. There are some things that are more beneficial for WP Engine users.
Chris: Yeah.
Jason: There's another open-source plugin -- we just 1.0 with it in December -- is WP GraphQL Smart Cache, so it's caching for WP GraphQL. More importantly, cache and validation.
Cache in GraphQL is easy. Invalidating GraphQL is a little more difficult because GraphQL queries, you have one endpoint that can have arbitrary queries with arbitrary resources returned. So, invalidating is a harder thing.
I've built that. It's an open-source plugin. There are requirements for hosts to play nice with it, though. And so, WP Engine is the first host that plays nice with it.
We're not closing it off, so we have a host guide, so other hosts can play nice with it as well. But yeah, so I work closely with WP Engine and other folks here to make us the first host that supports it.
Chris: Yeah. That's cool. By caching, you mean server-side cache, right? It must be, right? That's all WP....
Jason: Network cache, so you could use get requests to make your GraphQL queries and benefit from network cache, like HTTP caching. And so, you can send your query over a get request. It'll be cache ... the first time, kind of like in regular WordPress, in a classic rendered WordPress page.
You'd hit the page. The first visitor is going to build the page in WordPress, and you'll get a response. Then every other visitor is going to hit a cached version of the page, so usually millisecond responses.
Chris: Yeah.
Jason: GraphQL now can work the same way. The first time a query is executed, it'll make its way to WordPress and execute. Then after that, it'll be served from cache until... And so, this is where the magic is. WP GraphQL Smart Cache analyzes the query that you made and determines what relevant events should have validated.
If you queried for a list of posts, it knows that any time you publish a new post, that query should be invalidated. Or if you edit one of the posts that was returned in the response, it should be invalidated.
Chris: Yeah. I find caching so freakin' complicated. Even today.
I have a personal blog, chriscoyier.net. I write WordPress posts on there. It's just off-the-shelf WordPress. But there's some caching involved because it's on Flywheel/WP Engine, right? There's some caching that I don't even understand that happens just at the host level. Probably a reverse proxy or whatever.
Then I put Cloudflare in front of it because it does a bunch of extra bonus stuff that nobody else does that's good for performance. I like Cloudflare, so there's that.
Then there's internal WordPress caching. Who knows. I don't even know. [Laughter]
There's all that stuff so, if I edit a post and hit the edit button, I have no mental model of when. Then let's say I were to go on Mastodon and say, "Hey, read this article that I wrote." Will they see the edited post or will they see some old, cached version of it?
I literally have no idea, and I'm often bitten by it, and it annoys me. I'd almost trust this more knowing that what's rendering it is a GraphQL request and there's one level of cache in the way, and this plugin is handling it. It seems appealing to me.
Jason: Yeah. I wish this was like I could share my screen and show something.
[Laughter]
Jason: Yeah, so wpgraphql.com is a Next.js site hosted on Atlas. WP Engine Atlas, you've talked about this.
Chris: Mm-hmm.
Jason: WP Engine Atlas is our hosting platform that allows you to host your WordPress site but also your JavaScript site. Usually, you've had to turn to other vendors like Netlify or Vercel or whatever to host your JavaScript, so you'd have your WordPress hosted in one place and your JavaScript hosted somewhere else.
With Atlas, you can host your WordPress and your JavaScript under the same place.
Chris: Okay. Yeah.
Jason: One bill to pay and one support team to talk to and things like that. So, wpgraphql.com is a Next site, and I can publish. My backend is still WordPress (for most things). I have some data getting pulled from Markdown in my repo for docs and things like that.
If I publish a blog post or edit a blog post on my Next.js site, you'll see the changes within like a second of me making the changes.
Dave: You can trigger that incremental build because it's the same service.
Jason: It's not even like a webhook to my build service. For me, I'm using Next incremental static regeneration.
Dave: Mm-hmm.
Jason: What that means is I can do my build once. Like if I published a new post, for example. That's a URL that doesn't exist on my static site yet. If a visitor visits that URL (at runtime in Next) it will make a query to WP GraphQL with that URL and say, "Hey, does this thing exist?" And if so, WP GraphQL returns the data, builds the page in Next on the fly, and then creates a static page in Next so that the next user sees or the following users see a static page.
Chris: Where is that cache? Is that a Vercel thing or does WP Engine do that too?
Jason: Yeah, so WP Engine Atlas, it's hosted on Atlas, so all the JavaScript is deployed on Atlas. Then there's the static component and then the dynamic component.
Most of it is done by Next, like the framework. But then Atlas, our host, is the one that stores the static version of the page and returns the static pages - much like Vercel or Netlify would do if you hosted with them.
Chris: That's very cool. That's some modern stuff.
Jason: Yeah. I don't have to rebuild my site every time I make a change.
Dave: I'm just thinking through this. You know the traditional WordPress, we'll call it. That flow of, like, I just want to make a change, please. You know?
And you're kind of just praying the change makes it and doesn't cause problems, like if you're redesigning a theme or something like that.
Chris: Right.
Dave: Then every time you deploy, you risk taking down your whole WordPress, right?
Jason: Yeah.
Dave: This seems very cool that it's all in the same host or whatever, but you could kind of deploy parts independently of each other. That's kind of cool to shim that GraphQL layer in between just to solve that little problem of, like, "If I upgrade WordPress, it's going to take the rest of my site down, so I don't want to do the upgrade WordPress." Yeah.
Jason: Yeah. One of the cool things about that, too, I was trying to prove a point one time, so I intentionally put errors in my WordPress site so that the white screen of death in WordPress. I don't know if you've heard of that term or experienced it yourself.
Chris: Mm-hmm.
Dave: Yeah. Yeah.
Jason: I did that on purpose. I said, like, I'm going to tank my WordPress on purpose and wpgraphql.com is still served because it's static files. Right?
Dave: Mm-hmm.
Jason: Even if it tries to rebuild a page, incremental static regeneration in Next will try and rebuild the page. But if it's getting errors from WordPress, it will continue serving the static files.
Chris: The old one? Clever.
Jason: If your WordPress site is down for whatever reason -- for my case it was intentional -- if you made a mistake or a plugin that you just updated.
Dave: A plugin update, a million things, yeah. Right.
Jason: Yeah, exactly. Your static site can still be served. It really comes in handy, in my opinion, too, for agencies or whatever or a business that's rebranding and you're totally redesigning your site.
A typical workflow in WordPress for this is like, okay, we're going to clone all your data to a different WordPress install. We're going to work on your new theme over here. Then on launch day, we'll tell everybody to stay logged out of WordPress, and we'll do this switch. Then you change the DNS to the new WordPress and all that stuff.
Chris: Right.
Jason: With headless, right now my content for wpgraphql.com, I have my Next.js front-end. Before that, it was a Gatsby front-end. It's just data, right? I was able to have my Gatsby site live while I'm working on my Next site simultaneously on the same WordPress install.
I didn't have to set up a separate WordPress install. I just point both front ends to the same endpoint, and one of them is live for users to see. The other one, I'm hacking on making it work.
Dave: Mm-hmm.
Jason: I don't have to change anything about my publishing workflow. I don't have to tell the other authors that write content or edit in the site to do anything different.
I could rebrand my site. I could build new templates. I could experiment with different technology.
I went from Gatsby to Next. I was experimenting with Svelte and Express and all these other things. The same WordPress install. I don't have to change a thing.
Chris: Yeah. Just don't mess with the data structure, but that's probably good practice not to anyway.
Dave: How does something like advanced custom fields fit into this? I know that's an old-time popular plugin. Can you siphon out the data in WP GraphQL?
Jason: I maintain a plugin. I create and maintain a plugin, WP GraphQL for ACF as well.
It reads the registry of advanced custom fields, field groups, and the fields that you manage with that plugin and it maps it to the GraphQL schema. Yeah, you can create field groups with ACF and then use GraphQL to query those fields.
It supports all the core ACF field types. You have text and text area and various relationship fields. Then the ACF Pro has flexible content fields, which a lot of folks use as like a page builder where you can create groups of fields, and then you can add those groups to your page in any order and drag and drop and rearrange them. A lot of folks use that feature as a page builder, and WP GraphQL for ACF supports that as well.
Chris: Nice. I guess that complicates types a bit, right? GraphQL is fully typed, right? If they have some - I don't know - date type or something, you better hope that whatever data it has is compatible with that. Was types a pain in the ass with all this?
Jason: Yeah. GraphQL comes with some common scaler types, right? You have your string integer float bullion - whatever.
Chris: Yeah. Right.
Jason: Right now, WP GraphQL just supports those out-of-the-box, the core GraphQL types. A date field, for example, is currently returned as a string. Not always ideal, so we do support the ability to register custom scaler fields or scaler types. We don't ship any at the moment. We are exploring it.
Common ones like date or date/time, or whatever, email, maybe URL, some of those common ones, we'll probably support in the not too distant future. But at the moment, we just support the scalers that the GraphQL spec supports.
Chris: You support mutations, too, through this plugin? It's not just a query-only thing, right?
Jason: Yeah. WP GraphQL supports mutations, so you can create, edit, delete things like posts and categories and tags and any custom post type, things like that. And it respects the permission system in WordPress, too.
WordPress has custom post types, right? You can have houses and cars and whatever it might be. You can grant permissions to those, like what user capabilities are required to edit and delete and update.
WP GraphQL respects those things, too. If you're not authenticated and you try and execute a mutation, it's not going to work - unless it's a public one like commenting. But if it's creating a post or editing posts, it'll reject it if you're not authenticated.
If you're authenticated (making the GraphQL request), then it checks who you are and what capabilities you have before allowing you to do what you're trying to do. But yeah, it's strongly typed as well, so there's the input API for GraphQL where it validates, "Oh, you're trying to pass an integer for the title and it requires a string," so it'll do some of that validation free for you - or whatever.
Chris: Oh, yeah. That's what I was mostly curious about is how complicated that gets because PHP isn't typed. I don't know when it gets complicated. Maybe it just doesn't because it's so forgiving with stuff like that.
Are you passing, like, are your categories enums, and if you pass in one that's an invalid enum, it rejects it? I don't know. I don't even want to know. [Laughter]
Jason: Yeah. Things that are pretty dynamic like that, like categories, are not going to be an enum because every time you add a new category it would change your schema and could potentially, like, if you deleted a category and it was an enum, then your schema changes in a breaking way. We don't do that.
Chris: Yeah.
Jason: One thing on mutations, since we were just talking about ACF, the ACF plugin, the WP GraphQL for ACF plugin does not support mutations right now. You could query your ACF data, but you can't mutate it at the moment.
Dave: Hmm... Okay.
Jason: There is some community contributions, like there are some community plugins that have explored mutations. I at the moment personally don't support that feature.
One of the reasons -- there's a feature in the GraphQL spec called the One of Directive. It's not in the spec. It's an RFC to the GraphQL spec. I'm waiting for that. Once that makes its way to the GraphQL spec officially then to GraphQL PHP then I would work towards supporting mutations in ACF. But probably don't want to dive into that topic. It's a loaded topic on its own.
Dave: Yeah.
Chris: I bet it is because I also suspect, like, don't you want to work on stuff that everybody uses? It seems like the longer you're in it, you're going to get pulled into the nichiest of niche stuff.
I would just guess that 95% of all usage of WP GraphQL is just query only anyway. It's just, I want to build a headless website, so I need a way to query stuff. I'm going to install this thing, and I'm going to query the hell out of WordPress with it.
Who is even doing mutations at all? Does that mean you're building an alternative WordPress to edit content and push it back up? It just seems--
Jason: When I was at the newspaper, one of the React apps that we did build was--
Like I mentioned, we had 54 newspapers on WordPress, and I was an admin on all 54, for example. So, when I leave, somebody has to log into 54 sites and make me not an admin. That's a little bit of time-consuming effort.
We did have an app where you could do stuff via GraphQL mutations across X amount of sites from one interface. You could find me and make me not an admin on 54 sites with a couple of clicks.
Chris: Yeah. That's a pretty good use case.
Jason: Things like that, it's like we weren't making an alternative publishing experience necessarily. But we were making time-consuming tasks less time-consuming.
Dave: Well, speaking of that, so I've set up some GraphQL in my day. Getting that little explorer up and going in a node service isn't too hard, I'd say. But the trick is getting the schema, getting whatever if you're doing reducers and whatnot, and then getting all the data stuff mapped to your MySQL (in WordPress case) or PostgreSQL. That stuff seems like the kind of nitty-gritty hard stuff.
What's the process of setting up WP GraphQL? It looks like the docs just say you start from, like, add plugin. Is that kind of how it goes?
Jason: Yeah. Yeah, you install and activate the plugin, and it will give you the graphical IDE in your WordPress dashboard. You can use other ones too like there's desktop graphical apps or whatever that you can install and point to your endpoint, too. But you get one in your WordPress dashboard, and you can start querying stuff right away.
WordPress has some registries under the hood like a post type registry, a taxonomy registry, settings registry, things like that. WP GraphQL uses those registries to figure out what your CMS is made up of, what post types you have, what taxonomies you have, things like that. And it uses those registries to build the GraphQL schema for you. It tries to do as much of this stuff as smart as it can so you don't have to do too much.
Dave: Yeah.
Jason: Then plugins like the WP GraphQL for ACF, the same thing. It looks at the ACF field group registry, and it maps the fields to the schema for you so that you can just start using the data from advanced custom fields right away.
There's a plugin, WP GraphQL for WooCommerce. WooCommerce is e-commerce for WordPress. And so, there's a community that maintain an extension. Jeff Taylor maintains that. And that does e-commerce functionality, so it exposes products and variations and all the things related to WooCommerce into the schema and does allow you to do things like checkout and add to cart and things like that via GraphQL.
Chris: That's pretty big, a pretty big endorsement from Automattic itself, I guess.
Jason: Yeah, so he doesn't work at Automattic. He does it on his own time. He'd probably appreciate sponsorship from them if they're listening.
[Laughter]
Jason: Yeah. He just works on it on his own time and has basically made a career out of doing consulting work for folks using it.
Dave: Maybe you said this, but the first version was like PHP to PHP, right?
Jason: Yeah.
Dave: Can I write GraphQL in PHP then?
Jason: Yeah.
Dave: And so, I can replace the whole weird WP query posts kind of junk I've littered every template with?
Jason: Yeah, you could. If you plan on still templating in PHP using some of the WordPress conventions, there might be some hoops you've got to jump through to prevent WordPress from doing what WordPress wants to do.
Dave: Mm-hmm.
Jason: But yeah, I've built PHP-rendered themes using GraphQL instead of the traditional loop or whatever.
Chris: Really?
Jason: You can.
Chris: Wow. That's appealing.
Jason: I would still... At this point, unless there was some business constraint, I don't know why I would do that at this point.
Dave: Yeah.
Jason: If for some reason I wasn't allowed to use JavaScript, React or whatever, then I might go that way.
Dave: Yeah. I can think of times. I remember times where I've had to do lazy joins or something like that by querying all the people and then querying all the companies - or something like that. Kind of joining those together.
It would be cool if you could just write the JSON asyntax and be like, "Give me these guys." That would be a lot nicer.
Jason: Yeah. Yeah, you can. If you do have a need and you are doing stuff in PHP, you definitely can. For sure.
Dave: Yeah. Okay. Sorry to get weird, but I was just like, "Wait. If it's PHP first, then maybe."
Jason: Our case, it was one PHP site talking to another PHP site, so it was less about the same site getting data out of itself. It was more, how can I get data from another PHP site, basically.
Dave: Yeah. Can you subscribe then, too? Is it we can have real-time WordPress?
Jason: That's kind of what we built at the newspaper. GraphQL has queries and mutations, and then the probably under-talked-about feature is subscriptions. WP GraphQL, at the moment, doesn't officially support official GraphQL subscriptions.
I've experimented with it. I have a video on YouTube where I show it. I show proof of concept working with real-time stuff.
We kind of built that system at the newspaper, but it wasn't official, like GraphQL spec'd subscriptions. It was like our own kind of proprietary take on it.
Chris: It's the idea, like, if somebody -- if two people were looking at a post at the same time and one of them left a comment, the subscription could theoretically be like, "Ooh, there's new data. I'm going to plop that comment right on the page," without even a refresh or anything.
Jason: Yeah, exactly. Like collaborative editing type of things could be supported by that.
In my mind, so Gutenberg is the block editor in WordPress. I don't know if you use that on your WordPress sites or not.
Chris: Indeed.
Jason: I'd imagine you can picture this. You have these blocks where you're building your content. Right now in WordPress, there's post-locking, right? If you're editing a post, I can't go in and edit the post at the same time.
Gutenberg uses the REST API, so this would take a whole lot of work to actually get this to work, but in my mind if Gutenberg was using GraphQL, each block could subscribe to, "Hey, is somebody else editing this block?" and can get data about that in real-time so I could see, oh, me and Chris could both edit the same post at the same time. It would just lock the block that he's editing (while he's editing that block).
Chris: Oh! Independent locking because I'm like, "Are you sure what you're saying?" because you're talking about CRDTs and operational transforms and a real shitty world of complexity. But not if you lock blocks. If you lock blocks, it's fine. Just let them blast. Yeah.
Jason: Yeah, so that's like I can picture. It's not going to happen, I don't think, because WP GraphQL is not in WordPress core, so Gutenberg is not using it, obviously. They're using the REST API.
Chris: Mm-hmm.
Jason: There is collaborative editing potentially being worked on by the Gutenberg team at some point. They're not, I don't think, going to go a GraphQL route to solve it. But in my mind, you could picture that.
Okay, if I could do mutations per block and queries per block and subscriptions per block, then I could build this UI where I can see who is editing which block in real-time. Then we could collaboratively edit in Gutenberg.
I think the problem can be solved other ways, and they're probably going to ultimately solve it in another way. But I can picture a world where GraphQL subscriptions will make it.
Chris: Yeah. It seems like it. It does seem like modern apps, generally, the assumption is that there is real-time possibilities. Like Notion is useless if it doesn't support multiple people editing the document at the same time. There are just some assumptions about that.
WordPress sometimes falls behind in that stuff. I'm sure that they're thinking about it.
That is a question. It sounds like - I don't know - so far, you've been like, "WordPress is going to do what WordPress is going to do," kind of thing. Is that how you generally think? Do you try to get involved with that and push them a certain way?
For example, I remember even when the REST API became a thing, it felt overdue. It felt like, "Come on. This thing doesn't even have an API?" Then when it landed it was okay, and now it's fine. But now it's almost like, "Really? Are you just going to ignore GraphQL?"
Are they slow-boating it on purpose? Do you have any idea? Are you expecting a phone call someday, like, "I think we're..."?
Jason: Yeah. I haven't had official conversations with the WordPress core committers about whether GraphQL should be in core or not. I've had casual conversations with some folks that have influence.
I haven't gotten involved, especially when Gutenberg was brand new. I tried to get involved in the direction it was going because I was working on WP GraphQL at the same time Gutenberg was being started.
Chris: Mm-hmm.
Jason: I was like, "Hey, there are a lot of things that could be done differently so that server APIs could make use of Gutenberg blocks." I tried to influence stuff there with little luck, and I kind of backed off. I wasn't getting much support from the core committers there, so I kind of backed off.
Yeah, as far as GraphQL being in core, I think there's some big benefits of GraphQL API being in WordPress core, but there's also, like I mentioned earlier, I'm waiting on a change to the GraphQL spec for this one of directive. When that comes out, there's going to be breaking changes to WP GraphQL.
It'll benefit the users, but it will be breaking changes, so you'd have to upgrade to a major version and probably change some things in your app that is using it. So, when it comes to the core WordPress, when the REST API was merged into core it was, I think, 2016, and there are bugs that still exist from then because once you put something into WordPress core, even if it's a bug, it's a feature now for 43% of the Web.
It's very difficult to iterate in WordPress core. There are things that haven't changed in many years.
Chris: Especially with things that relate to data, right?
Jason: Yeah, and so putting the GraphQL API into WordPress core, there's a lot of benefit to it, I think. But I don't think we're at a point yet, and I don't know when or if we will be (even in the near future) where to me it would make sense.
If the rest of the world is using GraphQL spec 2023 and WordPress is on GraphQL spec 2021, then the whole world is using modern GraphQL tooling and the WordPress community is using legacy tooling. Right? So, to me, it makes sense as a plugin, at least for now. If you're doing headless WordPress stuff, at least right now it's growing.
Obviously, the popularity is growing, but compared to the size of the WordPress community, it's a pretty niche thing still. We've got 20,000, 30,000, 40,000 installs of WP GraphQL. WordPress is 43% of the top ten million. So, in comparison to the community, headless is still small.
Chris: Yeah. Right.
Jason: And that's just for WP GraphQL. The REST API could have more usage that I don't know about. In general, it's small. So, if there are changes, you're opting into this community, so I think installing a plugin is not this wild ask of you to install an updated plugin. But then it allows you to opt into the version that works for you.
If we do make breaking changes, like this one of directive, when that makes its way into GraphQL spec and GraphQL PHP on the WP GraphQL, you will have to make the conscious decision to say, "I want to opt into these new features that might cause me to break other things and have to rebuild my app." You get to opt into that.
If it's WordPress core, what are you going to do? You have to stay on some old version of WordPress and deal with potential security issues and stuff that are being patched on newer versions. It allows you to pick which version works for you, and so I think iterating as a plugin.
Chris: Yeah. WordPress, it's built with a plugin architecture for a reason. It's like this is that reason.
Dave: It probably saves WordPress, too, from migration hell. If they had to change something, that stinks for them.
Jason: I've proposed this idea, and I might talk with some folks officially about this maybe in the near future. WP CLI is a CLI tool for using WordPress. It's not part of WordPress core. It's a side thing you install on your machine and then you can run CLI commands against WordPress. It's not WordPress core but it's recognized as the official CLI client for WordPress.
I think there is room for maybe WP GraphQL to take that position where wordpress.org or the WordPress Foundation or whatever recognizes, "Hey, if you're going to do stuff with GraphQL, let's all collaborate on this thing," because you can go build your own CLI client for WordPress and nobody is going to stop you. But you'd be probably wasting time because there's a bigger community effort around WP CLI.
Chris: Oh, I see where you're going with this. You want to almost get recognized as the canonical one. You probably already are. Although, there is one competitor, isn't there, at least?
Jason: There's at least one. There were a couple before me, too.
When I was researching it for the newspaper, I was researching. I found two. There was another one called WP GraphQL and one called GraphQL WP.
I reached out to both of them. I ended up merging with one of them. Edwin Cromley had one called WP GraphQL as well. And then the GraphQL PHP one.
We hosted on WordPress VIP at the newspaper, and the GraphQL WP one wasn't... VIP has very strict code quality controls, and that one wasn't compatible. But I reached out to the guy. I talked to him a little bit. He kind of seemed like he built it for one specific project and wasn't maintaining it.
Chris: Hmm...
Jason: But then the other one, WP GraphQL (the same name), we ended up working together. He merged his stuff into mine. We worked together for a while. Then he kind of dropped off after a few months, and I actually haven't heard of him in probably a few years now. But we worked together on it.
But then there's another one called GraphQL-API, or something like that. That's another one. I think it takes a much different approach to schema design and stuff than I think makes sense.
But yeah, there are other options. You could build your own option as well.
There's a plugin on the WordPress ... repo that adds a GraphQL endpoint specific to WooCommerce that's unrelated to WP GraphQL. So, you can build your own.
Chris: Does it not use the REST API? It probably doesn't, right? Your origin story said, "Using the REST API was too slow." Your GraphQL, you must do your own internal querying and such.
Jason: Yeah.
Chris: Yeah?
Jason: Yeah, exactly. Yeah, it does not use the REST API under the hood at all. Yeah, when you make a GraphQL query, it uses other core WordPress mechanisms like WP query and WP user query and things like that. It still takes advantage.
WordPress under the hood has various caching layers as well. If you use WP query, that query will be cached. If you have a persistent object cache like Redis, Memcached, or something like that, the results of that query are cached there and then you're not hitting SQL every time you make that query.
WP GraphQL respects those things. Then there's hooks and filters under the hood in WordPress. And so WP GraphQL tries to use as much of those parts of WordPress as it can.
Then it adds. I don't know if you've heard the term data loading in GraphQL land, but it helps reduce that N+1 problem that can happen with GraphQL. And not just with GraphQL; with anything. But it comes up in GraphQL a lot.
Dave: It's easier to do in GraphQL.
Jason: Yeah.
Dave: It's easier to bottleneck yourself.
Jason: I mean it's pretty easy. Like you mentioned, you were doing custom joins earlier where you had to get a list of all your customers and then all their businesses - or whatever you were saying you needed to do.
Dave: Yeah. Yeah.
Jason: You could do it there, too. You'd say, "For each customer, go get their business," and so that's like, for customer one, do a query to get business. For customer two, do a quick... So, you have your N+1 problem.
A lot of people do it in normal WordPress and not even realize they're doing it. A lot of people have the loop, the WordPress loop, and then they call something like, "For each post, get the author." Okay, well, for 100 posts, you're calling 100 get the authors.
Chris: That's a lot.
Dave: Right. Yeah, it's funny. Usually, it doesn't matter.
This is kind of something I've been dealing with. Sometimes it doesn't matter. It's fine. It's fast. But then when you think you can do that trick at scale or a page with 1,000 posts, for some reason, then it's like, "Oh, no. I have locked the database up pretty bad," for every user.
Jason: Yeah, so WP GraphQL tries to help with that, like in that example if you query 100 posts and then the author on each one. It'll do the query for the 100 posts, and then it waits to get 100 posts. Then it does one query to get all authors of the 100 posts instead of 100 more queries for each author. It's one query for the authors of the 100 posts.
Dave: One hundred author IDs or whatever. Yeah. No, that's cool.
Yeah, so I was thinking back. Chris, maybe you remember this. We went to Jamstack Conf three years ago - or something like that. There was kind of a running joke.
It was like, "And we have a WordPress site," and people were like, groan, you know.
Chris: I groan at your groan.
Dave: Well, that was sort of like the idea.
Chris: Right.
Dave: That was kind of the vibe. I think, even three years ago, it was like WordPress plus Jamstack was kind of like a mess. I don't know. Are you feeling like WordPress is kind of like a really great Jamstack candidate or is that kind of the goal to make WordPress Jamstack-y? What's your vibe?
Chris: I want Jason's answer, but I'll say one thing I want to make sure I say in this is GraphQL might be a component of this or it might not. What needs to push WordPress--
I think, to ask people to just do PHP templating for the end of time for WordPress is not going to happen. That DX world, there's already a very large divide between what's happening in real, modern DX stuff and what's happening in WordPress. The divide is getting wider and wider, so there's got to be a way, eventually, a canonical way to build a WordPress front-end that's not PHP templating.
I don't know what it is or what the answer is going to be, but it's got to be something, right? Am I crazy? It's got to be something.
Jason: Yeah. What did they do? I think the Jamstack survey or whatever it was at some time toward the end of the year. I think they did the results at the Jamstack Conf in, what, November maybe. But they did show.
I think it's no surprise that WordPress typically tops the charts of worst developer experience of frameworks. It's pretty high up there every year. People don't like doing development in WordPress.
But then the Jamstack survey was showing that, okay, WordPress is still the most widely used CMS. Everybody knows that. But the developer experience of headless WordPress is also significantly higher. People like doing headless WordPress development compared to traditional WordPress development.
The developer experience, folks are responding positively to it already, like in surveys like that. So, the canonical way, I think that's interesting. There are a lot of different companies working on, like, "Okay, what does a canonical headless front-end look like?"
It's tricky because, every three weeks, there's another JavaScript framework out there. So, what's the canonical way? I don't know. What's the canonical way to build a JavaScript front-end, period? There isn't one. So, that's tricky.
I think, with GraphQL, we're trying to say, "Okay, whatever you like to work with, we're going to try and make it easier." That said, like at WP Engine, we're working on a framework called Foust, and that's probably what you experience when you use local and did this one-click stuff in Atlas. We have a framework called Foust.
Chris: Yeah. Real quick, yeah, Foust is part of that. I do want to think, so the word Atlas isn't just one thing. At least to me, right? It includes this Foust thing that you're about to talk about, and it's some node server or something. I don't even know if that's a part of it. And it's a blueprint of WordPress that includes the WP GraphQL plugin because you can't do any of this unless that thing is installed and activated properly. Atlas, is it true that it's a bunch of stuff combined?
Jason: It is, but they're all pieces that are optional, too.
Chris: Okay.
Jason: You can run a Gatsby site on our Atlas hosting. Our Atlas hosting, you can host a WordPress site and then your JavaScript.
We don't care what JavaScript framework you're running. You could use Svelte or Next or Gatsby or whatever. You don't have to use Foust.
We're providing Foust as an open-source tool for folks that want to use it, and we'll probably support it better on Atlas than maybe other providers will.
Chris: Mm-hmm.
Jason: Kind of like Vercel does secret things that make Next run better on Vercel than elsewhere. And Gatsby, with Gatsby cloud, they do secret things. You could do it, but it takes some engineering under the hood to do things.
We'll probably end up doing stuff like that with Foust where it works better on WP Engine, but you can use Foust anywhere.
Chris: I stopped you before you explained it, though. What is Foust?
Jason: Yeah, so that's what I was going to say. Foust is a JavaScript framework, and it is built on Next at the moment. There is potential that it could work on other things other than Next, like Svelte or whatever. But at the moment, it works on Next, and it brings some features of traditional WordPress development like the template hierarchy - conventions like that. It brings that to headless front-end.
Like I was saying, on wpgraphql.com, like I mentioned earlier, when I publish content or write content, within a second you're going to see those changes. One of the reasons that works is when you visit a URL in your headless front-end, it sends that URL.
Foust, the framework, is going to read that URL that you're requesting in Next. It's going to read that URL, know how to send that to WP GraphQL, make a query to figure out what data that URL represents, like, is that URL a user? Is it a blog post? Is it a category archive?
It figures that out, gets some data, and then determines what template to return. Very much like WordPress itself, it has what's called the template hierarchy. You visit a URL, and it knows whether you should return an archive template or a single-page template.
Chris: Wow. So, you don't even have to write a GraphQL query necessarily? It will guess at the correct one to write for you?
Jason: Kind of. Kind of, so it's a two-step thing. It takes the URL, figures out some basic information about what the thing is, and it returns that data to you. Then there's a template system very similar to the template hierarchy in WordPress.
WordPress has a file-based template hierarchy where you say single.php will render for blog posts and pages. But if you do single-post.php, that will override it for the post-post-type, and single-page will--
So, it's a very similar concept. There's a config, a Foust config, where you can say my single blog post will use this JavaScript file. You get to decide what the file is yourself. We have some smart defaults or whatever. But you ultimately get to decide where your templates live.
You pass that to a config file, and then you write your templates very similar to how you would in PHP templating or in WordPress templating. But you get to do it in React.
At your template level, you write the GraphQL query that you need for that specific template then, and you'll get a payload of basic data back from Foust. It'll tell you the ID of the thing that you're looking at. It'll tell you the URL and what type of thing it is, whether it's a user.
Chris: Then you pass that to the GraphQL query.
Jason: Yeah, and then you can use variables in GraphQL, so you would say, "Okay. Now that I know this thing is a user," or a post, "here's what data I want for my template."
And so, you use GraphQL query. Then use React components to render it. You can do your style.
If you're a CSS and JavaScript fan or a Tailwind fan or whatever you are, you can do your styles, your JavaScript, and your GraphQL query in the same file. Then you can break it up into components and use GraphQL fragments at the component level so that each component can be self-contained. It has the markup that it needs.
Dave: Yeah.
Jason: It has the styles, whether it's Tailwind or CSS and JavaScript or whatever you're doing, or a separate CSS file even in the same directory. However you do styles, you can have it componentized, and it has your GraphQL, your data dependencies, your markup, and your styles. That's kind of the dream, or at least my dream.
I think a lot of developer experience dream is like, "How can I build these isolated components that have everything they need?"
Chris: Yes!
Dave: Yes, please.
Jason: Yeah.
[Laughter]
Jason: Yeah, GraphQL and fragments. I could do a whole episode on fragments alone. Fragments are amazing in GraphQL. That's one thing that probably doesn't get talked about enough in GraphQL. When people do GraphQL versus REST comparisons, I think--
Chris: I know what you mean. You say a fragment is a comment, and every time I ask for a comment, I want these five things. But I'm going to put it in ten queries, and I don't want to rewrite that five things every time.
Jason: Yeah!
Chris: Yeah.
Jason: Yeah, because you're going to have a component that its job is to render comments, and it has specific data needs. You can say, okay, I can write a fragment in that component that says, "Okay, whenever a comment is asked for in the schema, I want X, Y, and Z fields, so I could have this component."
Then higher up, like maybe I have a list of comments component, I import the individual comment component and the fragment, so my list of comments has a fragment as well saying, "Hey, I want a list of comments." It imports the comment component and the comment fragment.
Chris: Right.
Jason: Then it uses that in the query. If you need to change, like, "Oh, we need to add this new field to our comment component," you just go to that one component file. You modify the fragment. You modify your markup and you're done.
You don't have to do this, like, "Oh, okay. We fetch from REST API over here. We transform data over here. We do this thing over here." Right?
You just go to the component that needs it. You change your fragment. You change your markup. You're done.
Chris: Yep. Unless you're in TypeScript. Then you've got to go find the type for comments and change it there, too.
Jason: Yeah. But even with the GraphQL API, this is going to sound super weird. I built a strong type API, but I still don't use TypeScript. But there's a lot of tooling out there that will autogenerate your types for you. You just show it a GraphQL endpoint and it will generate the types for you.
I can't speak... I just mentioned I don't use TypeScript, so I can't speak super in-depth about that, but there are tools that auto do it for you.
Chris: Well, all right, Jason. That was as in-depth as I ever could have hoped for on all this. I really appreciate you digging into this. You really made this your life, in a way, or at least your professional life.
Jason: Yeah.
Chris: It shows, I'll say. Any final thoughts or questions, Dave?
Dave: Oh, yeah. Thanks for coming on. It's really cool to see how you're helping push WordPress forward and give people options for their data and templates. That's pretty cool.
Before we go, how can people follow you and give you money?
Jason: Yeah, so I'm on Twitter, @jasonbahl. Last name is B-a-h-l. And @wpgraphql on Twitter as well. GitHub.com/wp-GraphQL, wpgraphql.com.
I get paid by my employer to work on open source. I don't solicit money from the public. But if you really want to send me money, WP GraphQL is on Open Collective. So, if you really do feel like you want to contribute to the project, then I usually just send that money out elsewhere, like I give money to GraphQL PHP, the maintainers of that, and things like that. So, if you are interested in that, it is on Open Collective, so you can donate that way too.
Dave: That's sweet. Thank you so much for coming on the show. We appreciate it.
Thank you, dear listener, for joining us here in 2023 on the ShopTalk Show adventure. Be sure to star, heart, favorite this up in your podcatcher of choice.
Follow us. I don't know where we're at. I think we have a Twitter account, technically. [Laughter]
Then you can join us over in the D-d-d-d-discord, patreon.com/shoptalkshow.
I guess we should say. Right, Chris? No ads for right now. We're kind of going no ads for a while. You may here a CodePen or a Luro ad in the future.
Chris: Yeah. I'm hesitant to say totally no ads. It'll be self-serving ads, but it feels very ad-free for us because we're going to not have third-party ads, I guess. First-party ads only.
Dave: First-party ads, and if your company is super cool and wants to come to us directly, we can make that happen. But anyway, that's just a programming update for you.
Thank you, everybody, for listening. We really appreciate it. Chris, do you have anything else you'd like to say?
Chris: I don't think so. ShopTalkShow.com.