Build an App Using React and the GraphQL Plugin for WordPress in ~15mins

If you keep up with tech trends, you likely already know that GraphQL is one of the newer breakout technologies that people are gushing about. It’s an open source specification created and used by Facebook’s Engineering team that can be used to push and pull data between APIs and apps. REST APIs have traditionally been used for that purpose, but GraphQL has several advantages over them that you can read more about here.

If you work on the WordPress platform, you’ll be happy to learn that a GraphQL implementation exists for WordPress – the WPGraphQL plugin! The project was started by Jason Bahl and is being actively being developed by him and a number of other contributors. In this post, I’ll walk you through building a sample app that uses React and Apollo Client in the browser to fetch data from a WordPress site that’s running WPGraphQL. Let’s roll! 🏎💨

Building Our App

We’re going to build an app that allows you to search for blog posts. If any matches are found on the server, WPGraphQL will send back the data we requested for each post and our React app will render cards to the page for the matching posts. Here it is in action:

In order to use GraphQL, you need software running on the server to receive requests, process them then send back a response. Server implementations exist in most popular server-side languages (PHP/Node/Python/etc.). We’ll be using the WPGraphQL plugin on the server, which takes two existing PHP libraries for GraphQL (graphql-php & graphql-relay-php), and layers WordPress-specific functionality on top of them, so that it’s possible to run queries for blog posts, pages, taxonomies, settings, users, and many other WordPress-y things (these are referred to as “types” in GraphQL parlance).

Once the server supports GraphQL, you’ll also need a client-side library to help out with sending the requests to the server and receiving the responses that come back. Many such libraries exist. For our client-side app, we’ll be using Apollo Client.

Steps to Follow

1. Make sure you have node and npm installed and are mildly familiar with React and running commands on the command line.

2. Install and activate the WPGraphQL plugin on the WP site you’d like to pull data from. You should then be able to visit the /graphql endpont in a browser, such as example.com/graphql and see JSON output rather than your site’s 404 page. Don’t worry if you see a “Syntax Error GraphQL” message in the JSON output. That’s expected, since we haven’t sent a valid request to the /graphql endpont yet – merely visited it directly in a browser.

One important distinction to note here: with REST APIs, many different endpoints are used, depending on the type of data you need to send/receive. With GraphQL though, all requests use a single endpoint. The WPGraphQL plugin registers the /graphql route for that purpose.

3. Run these commands to get a fresh app up and running locally using Create React App:
npx create-react-app wpgraphql-app
cd wpgraphql-app
npm start

You can now open http://localhost:3000/ to see your app.

4. Install the npm packages we need.
npm install apollo-boost react-apollo graphql graphql-tag

Here’s a brief description of each:

  • apollo-boost: Package containing everything we need to set up Apollo Client
  • react-apollo: Apollo Client view layer integration for React
  • graphql: Library for parsing GraphQL queries
  • graphql-tag: Library that takes ES6 template literal strings and compiles them into GraphQL ASTs (Abstract Syntax Trees) that can then be passed into Apollo Client

5. Open the project in a code editor. In the /src/ folder of your project, delete all the files except index.js and style.css to clean things up a bit.

6. Replace the contents of /src/index.js with the code below, but swap out “http://example.com” with the URL of the WP site you want to pull data from.

You can see that we’re creating a new client using Apollo and providing it with the URL endpoint to use for GraphQL requests. We’re also wrapping our entire app in a new ApolloProvider and passing to it the client we created as the client prop. The result of this is that we’ll now be able to use the react-apollo library to make GraphQL requests anywhere inside of our app.

7. Replace the contents of /src/style.css with this code to give our app some style. 😎

8. You may have noticed that /src/index.js tries to import a PostsSearch component that doesn’t exist yet. Let’s fix that! Create a new /src/PostsSearch.js file and paste in this code:

This component provides the input in which users can type the text they’d like to search for. Once the search field is populated with text, it renders the PostsList component (which we’ll create next), providing the search query to it as a prop.

9. Create a new /src/PostsList.js file and paste in this code:

This is where the magic happens ✨. At the top, we’re defining a POSTS_SEARCH_QUERY GraphQL query. It takes in a search string as an argument and tells WPGraphQL to search for WordPress blog posts that match it, and send back their data. Notice that unlike a REST API where you have no control over which data is sent back in the response, here we are telling WPGraphQL exactly what data we’d like to get back, and the shape to put it in.

In GraphQL, “edges” represent connections between nodes, and “node” is a generic term for an object – in our case those objects will be blog posts.

You can also see that we’re using the Query component and passing to it our query as well as the search string to use as the argument it gets. Query handles all the heavy lifting and provides a render prop. We are immediately destructuring the three props we receive into loading, error, and data variables. After that we have some declarative JSX code to handle all possible scenarios. Different things are rendered depending on whether:

  • the query is currently in progress (loading)
  • an error has occurred
  • matching posts were NOT found, or
  • matching posts WERE found

If matching posts were found, we map over them and render out a PostCard component for each (which we’ll create next).

10. And now for our final PostCard component that will handle rendering each individual post card. Create a new /src/PostCard.js file and paste in this code:

That’s it! Once those four JS files and one CSS file are in place, you should be able to run npm start (if the app’s not already running), then visit http://localhost:3000/ and try searching for some blog posts. Any string you type will be used to search both blog post titles and their content, and the matching results will pop into view.

Let’s contrast our app from one using a traditional REST API for a minute –
If you were to build an app like this using a REST API, you’d potentially have to make multiple requests back to the server to get all the data you need. The first REST endpoint may take in a search string as an argument and respond with a list of the post IDs for the matching search results. You’d then have to take those post IDs and make another request back to the server to get all of the data you need for those posts (title, date, author, featured image, etc.). Extra, synchronous round trips like that back to the server can be expensive and slow down your frontend app. By contrast, with GraphQL, everything can be fetched in one request. For example, you could build a complex query for getting the most recent 10 posts, then for each of the authors of those, get some of their user data (name, email, etc.) as well as a list of their 3 most recent posts in a particular category. If you’re using GraphQL, all of that data could be fetched from the server in a single request and returned to your frontend app all at once, formatted in exactly the way you requested.

This example app merely scratches the surface of what can be done with these technologies. You can dig into the documentation for WPGraphQL to learn more about working with mutations (changing or deleting data), implementing authentication, defining your own GraphQL types, connections and resolvers, and much more.

Apollo Client also has lots more to offer from sending requests for mutations to the server (in addition to query requests, like the one we send in this example app), caching query data locally, providing you with a global app data store using Apollo Link State, pagination, and many other features.

Now go forth and see what other cool things you can build with these technologies. 😊

Querying Sticky Posts with GraphQL

Recently, a WPGraphQL user asked how to query only sticky posts with a GraphQL query. 

One of the great things about WPGraphQL is how customizable it is with hooks and filters, making it easy to extend the API for your needs. 

End goal

One (of many possible) solutions would be to allow the client to specify that they only want sticky posts as an argument on the posts connection query.

A query could look something like the following: 

query GET_STICKY_POSTS {
  posts( where: {onlySticky: true }) {
    nodes {
      id
      title
      date
      link
    }
  }
}

This query would allow the client to specify that they want posts, but onlySticky posts

This should give us what we were looking for, a way to query only sticky posts using WPGraphQL. 

The issue is that the onlySticky argument doesn’t exist in the WPGraphQL plugin, so if we want to use it, we’ll need to add it ourselves.

Register the “onlySticky” argument

To add this field as an argument, we can use the following snippet:

add_action( 'graphql_register_types', function() {
    register_graphql_field( 'RootQueryToPostConnectionWhereArgs', 'onlySticky', [
        'type' => 'Boolean',
        'description' => __( 'Whether to only include sticky posts', 'your-textdomain' ),
    ] );
} );

Here we hook into the graphql_register_types action, to make sure the GraphQL Type registry is ready to be hooked into. 

Next, we register a field to the GraphQL schema by using the register_graphql_field() method.

The first argument is the name of the Type to register the field to. In our case, that Type is RootQueryToPostConnectionWhereArgs. This is the Input Type that is used by the root posts field to provide filters to the query. 

The next argument is the name of the field we’re registering. Here, we’re using onlySticky as the field name. 

The third argument is an array to configure the field. We declare the Type the field should be is Boolean, meaning it should be either true or false, and provide a description for the field. 

At this point, our query would validate, as onlySticky would be a valid argument on the query now, but our actual results aren’t affected.

Filter the WP_Query to respect the onlySticky input

The next step we need to take is to filter how WPGraphQL resolves the query and make sure it respects the onlySticky argument that was input. 

We can do so with the following snippet:

add_filter( 'graphql_post_object_connection_query_args', function( $query_args, $source, $args, $context, $info ) {
    if ( isset( $args['where']['onlySticky'] ) && true === $args['where']['onlySticky'] ) {
        $sticky_ids = get_option( 'sticky_posts' );
        $query_args = [
            'posts_per_page' => count( $sticky_ids ),
            'post__in' => $sticky_ids
        ];
    }
    return $query_args;
}, 10, 5 );

Here, we filter graphql_post_object_connection_query_args. This filter can be found in the PostObjectConnectionResolver.php file in the WPGraphQL plugin. 

This allows for the $query_args that are prepared to send to WP_Query for execution to be filtered prior to WP_Query fetching the posts. 

Inside this filter, we check to see if the $args that were passed through the resolver from GraphQL include the onlySticky input, and if that value is true

If those conditions are met, then we define custom $query_args, by first getting a list of the sticky posts, then asking to query only those IDs and the posts_per_page equal to the number of sticky posts we have. 

Then we return the modified $query_args for WP_Query to use to resolve the query.

In action

Now, we can see our query in action. 

First, go set a couple posts to sticky, if you haven’t already:

Screenshot showing a few sticky posts

Then, using WPGraphiQL, execute the query, and the results returned should only be the Sticky posts!

GIF showing how the query with onlySticky set to true, and the results being only sticky posts

Conclusion

My hope is that this shows how easy it is to extend WPGraphQL for your system’s needs. The plugin is powerful out of the box, but if you have custom needs for your application, take advantage of the various hooks and filters in the plugin to make it work for you!

Introducing playground.wpgraphql.com

I’ve done many presentations about the WPGraphQL plugin, and I find myself showing demos of many of the same features, so in order to streamline the demos before my presentation at the 2018 WordCamp Phoenix, I created https://playground.wpgraphql.com

This site showcases examples of GraphQL Queries and Mutations on a live WordPress site with the WPGraphQL plugin active. The demos start out very basic, and as you work down the list, you will see progressively more advanced examples of GraphQL use cases, demonstrating both unique features of the WPGraphQL plugin and the broader GraphQL Query Language.

Enjoy.

New meeting schedule in the WPGraphQL slack

Over the past few weeks we have been working hard towards the stable 1.0 release of the WPGraphQL plugin. We have a plethora of issues in our backlog that we feel are necessary to resolve before the stable release. In order to try and organize our efforts a little bit better, and to make it easier for new contributors to come on board, we will be adding scheduled bug scrubs and office hours within the WPGraphQL slack organization. If you haven’t joined the slack organization yet, use the link on the community page to get added.

Starting the week of October 16th, the schedule for meetings will be as follows:

  • Bug Scrubs: every Tuesday and Thursday, 11:30am – 12:00pm MDT
  • Office Hours: every Friday at 10:00am – 11:00am MDT

If you are interested in contributing to the WPGraphQL plugin, we would love to have you join us for some of the bug scrubs if you can spare some time. We are looking for help on issues such as documentation, unit testing, and overall plugin architecture. If you are a consumer of the API, or someone modifying it for your needs we would love to hear how you are using the plugin so we can make sure we are making the right decisions for the future of the plugin, as well as the community. See you in slack!

WPGraphQL Featured on FreeCodeCamp

FreeCodeCamp is a popular YouTube channel that posts free videos about coding. Today, Jesse Weigel did a live coding session diving into using GraphQL with WordPress and after comparing a few options, he settled on using WPGraphQL.

Watching the video was eye opening. It was great to see that folks are interested in using GraphQL with WordPress, but it was also clear that the documentation and resources to get started using WPGraphQL are still pretty lacking. Documentation will be a focus over the next few weeks to make sure folks have what they need to get up and running with WPGraphQL.

Thanks, Jesse for featuring the plugin!

Check out the video from FreeCodeCamp here:

 

 

Tracing for WPGraphQL

In 2015, Huey Petersen wrote an article about instrumenting a GraphQL schema to track resolver times and provide insight into how the GraphQL server is performing. Since then Apollo Optics has taken the instrumentation to a new level, providing a SaaS solution for storing data about your GraphQL requests. The Apollo team has also been working on a proposal to standardize the instrumentation, and they’re calling it Apollo Tracing.

The proposed spec is still young, but the goal is to come up with a standard for how GraphQL schemas should record performance metrics for requests and their resolvers so that tools like Apollo and perhaps even GraphiQL or others can make use of these standard extensions.

While the spec is still young, having these metrics is pretty important for us, so we’ve introduced WPGraphQL Insights. It’s a plugin that adds tracing to your WPGraphQL server. The plugin is pretty early in development, so I wouldn’t suggest running it in production quite yet, but feel free to test it out on your local/dev environments and provide any feedback on the Github repo so we can make it better!

The near-future plans for the WPGraphQL Insights plugin are:

  • add the ability for the server to enable/disable tracing
    • add a settings page
    • define via a constant, ex: define( ‘GRAPHQL_TRACING’, true );
  • allow the client to request tracing in the response (see this discussion)
  • provide storage options for the trace data
    • We’re working with the Apollo Optics team to figure out how we can get the trace data from a WPGraphQL server into Optics
    • We’re experimenting with storing trace data locally in WordPress to some degree
    • We’re experimenting with sending the data elsewhere, like logstash/elasticsearch.

Here’s a look at tracing in action on WPGraphQL. Enjoy!

Using GraphQL Queries in PHP within your WordPress Theme or Plugin

GraphQL is most popularly known as a way to fetch data from remote sources via HTTP requests, but with WPGraphQL, you can access your local WordPress data in your plugin or theme via declarative GraphQL queries. An example use case would be a simple shortcode for a list of posts.
wpgraphql-basic-shortcode-example
Example shortcode that outputs a list of posts and is populated with the site’s content with a GraphQL query
Let’s look at how we can build a simple shortcode that populates a list of posts from the site and renders an unordered list with the post’s title and date. First, lets register our shortcode:
add_shortcode( 'graphql_basic_post_list', function( $atts ) {
  return ! empty ( $output ) ? $output : '';
} );
Now we have a [graphql_basic_post_list] shortcode but it’s not useful. Our end goal is to output a list of posts with the title and date, and we’ll use the ID as the “id” of each list item. Since we know what data we’ll need, we can start with writing our GraphQL query to get the data. Inside the shortcode function, let’s add our query. GraphQL queries are static strings, so we can simply add:
$query = '
query basicPostList($first:Int){
   posts(first:$first){
      edges{
         node{
            id
            title
            date
         }
      }
   }
}
';

$data = do_graphql_request( $query );
This will give us an array of posts, which contains an array of “edges” and each edge will contain a “node”. The node is our post object, and this is where the fields we requested are. In our case, we asked for id, title, and date. The raw data returned from the query should look like this (of course with your site’s data):
[data] => Array (
	[posts] => Array (
		[edges] => Array (
			[0] => Array (
				[node] => Array (
					[id] => cG9zdDoyOTI0
					[title] => Test GraphQL Basic Post List
					[date] => 2017-08-19 14:49:25
                )
            )
            [1] => Array (
				[node] => Array (
					[id] => cG9zdDoyOTE3
					[title] => Test Color Field
					[date] => 2017-08-11 19:42:10
                    )
                )
            [2] => Array (
				[node] => Array (
					[id] => cG9zdDoyODc0
					[title] => Denverpost Content in Gutenberg
					[date] => 2017-08-04 21:22:17
                )
            )
            [3] => Array (
				[node] => Array (
					[id] => cG9zdDoyNDA3
					[title] => Fieldmanager Test, yo
					[date] => 2017-06-28 16:25:13
                )
            )
            [4] => Array (
				[node] => Array (
					[id] => cG9zdDoyMzg2
					[title] => Testing a Gutenburg(sp?) Post
					[date] => 2017-06-23 21:02:57
                )
            )
        )
    )
)
This data looks pretty easy to work with! Now we just need to loop through the data and return our markup.
$edges = ! empty( $data['data']['posts']['edges'] ) ? $data['data']['posts']['edges'] : [];

if ( ! empty( $edges ) && is_array( $edges ) ) {
   $output = '<ul>';
   foreach ( $edges as $edge ) {
      $node = ! empty( $edge['node'] ) ? $edge['node'] : '';
      if ( ! empty( $node ) && is_array( $node ) ) {
         $output .= '<li id="' . $node['id'] . '">' . $node['title'] . ' ' . $node['date'] . '</li>';
      }
   }
   $output .= '</ul>';
}
This makes sure that we have an array of “edges” and if we do, it creates an unordered list and loops through the edges, creating a list item for each node, with the node’s id as the <li> id property, and the post’s title and date as the text within the list item. The complete shortcode, with an example argument for how many posts to query is:
add_shortcode( 'graphql_basic_post_list', function( $atts ) {
   $query = '
   query basicPostList($first:Int){
      posts(first:$first){
         edges{
            node{
               id
               title
               date
            }
         }
      }
   }
   ';

   $variables = [
      'first' => ! empty( $atts['first'] ) ? absint( $atts['first'] ) : 5,
   ];

   $data = do_graphql_request( $query, 'basicPostList', $variables );

   $edges = ! empty( $data['data']['posts']['edges'] ) ? $data['data']['posts']['edges'] : [];

   if ( ! empty( $edges ) && is_array( $edges ) ) {
      $output = '<ul>';
      foreach ( $edges as $edge ) {
         $node = ! empty( $edge['node'] ) ? $edge['node'] : '';
         if ( ! empty( $node ) && is_array( $node ) ) {
            $output .= '<li id="' . $node['id'] . '">' . $node['title'] . ' ' . $node['date'] . '</li>';
         }
      }
      $output .= '</ul>';
   }

   return ! empty( $output ) ? $output : '';
});
NOTE: this post was written using Gutenberg v0.9.0

WPGraphQL at WordCamp for Publishers

I hosted a workshop on “Content Syndication with the WP REST API and WPGraphQL” at the first ever WordCamp for Publishers on Friday, August 18, 2017 at the Denver Post building in beautiful Denver, CO. Unfortunately, there was no video of the workshop, but the slides for the workshop are here: http://slides.com/jasonbahl-1/content-syndication In the workshop, we covered how Digital First Media uses the WP REST API to syndicate millions of pieces of content per year across various WordPress and non-WordPress systems. We cover what we’ve learned about using REST, both positives and negatives. We looked at many of the frustrations we have with working with REST and how GraphQL eases some of those frustrations. We looked at what GraphQL is, how it applies to WordPress as an application data graph, and how you can use GraphQL today in WordPress with the WPGraphQL plugin. We walked through various features of GraphQL using the GraphiQL IDE. We explored the documentation that is generated for the GraphQL Schema using the GraphiQL documentation browser, then we wrote some queries. We queried for posts, posts with nested author objects and nested posts of that author. We looked at node queries, fragments, aliasing, variables and the cursor based pagination, even for data that’s typically not paginated, such as plugins and themes. We then looked at examples of how to extend the WPGraphQL schema to add custom entry points into the queryable WordPress Application Data Graph. The examples we looked at for extending the Schema included:
  • adding a root field
  • adding a custom field to the “post” schema
  • registering a custom post type with WPGraphQL support
  • registering a custom taxonomy with WPGraphQL support
  • adding a custom field to a custom post type where the field can be queried and mutated
  • adding a root field that resolves data from an external system (return a random “dad joke” from icanhazdadjoke.com (source code)
  • Finally, we looked at registering a new Type to the GraphQL schema.
    • We registered a “Syndicated Books” type which resolves with data from external WPGraphQL enabled servers.
The examples we looked at all exist in a plugin here: https://github.com/wp-graphql/wordcamp-for-publishers-demo-extension WPGraphQL is also going to be one of the projects for Contributor Day at WordCamp for Publishers on Saturday, August 19, 2017 at The Denver Post building. Even if you can’t make it to Denver, feel free to contribute remotely…you can submit issues, start working on pull requests for open issues, test the plugin on your own and write a blog post about it, or just simply star the GitHub repo and tweet about it.  

Optimizing WPGraphQL for WordPress VIP

EDIT: This specific issue has been addressed by WordPress core in version WordPress 4.8, but it still shows how to filter to override resolvers in WPGraphQL.

If you host your site with WordPress.com VIP, you can (and should) take advantage of the cached functions they provide to improve the performance of some WordPress core uncached functions.

If you’re using WPGraphQL in a WordPress.com VIP environment and want to have WPGraphQL take advantage of some of these functions, you can do so pretty easily.

In WPGraphQL, the TermObjectType, which is used for terms (categories, tags, custom taxonomies) has a link field, which uses the uncached function: get_term_link in the resolver.

WordPress.com VIP provides an alternative cached function: wpcom_vip_get_term_link.

Our goal here is to:

  • Find all termObjectTypes
  • Filter the resolver for the `link` field on those types, replacing the default resolver with our optimized resolver.

Let’s do this:

First, let’s only hook our functionality in after the Allowed Taxonomies have been registered and setup for WPGraphQL to make use of.

add_action( 'graphql_generate_schema', 'your_prefix_filter_term_object_fields', 10, 1 );

Now, let’s get the Taxonomies that are registered as allowed to show in GraphQL, and we’ll loop through them and filter their fields.

function your_prefix_filter_term_object_fields() {
  
  // Get the allowed taxonomies (taxonomies with "show_in_graphql" => true)
  $allowed_taxonomies = \WPGraphQL::get_allowed_taxonomies();
  
  // Loop through the allowed taxonomies, so that we can filter the fields for each termObjectType for each taxonomy
  if ( ! empty( $allowed_taxonomies ) && is_array( $allowed_taxonomies ) ) {

     foreach( $allowed_taxonomies as $taxonomy ) {

         // Get the taxonomy object as we'll need the "graphql_single_name" property to use in the filter
         $tax_object = get_taxonomy( $taxonomy );

         if ( ! empty( $tax_object->graphql_single_name ) ) {
             add_filter( "graphql_{$tax_object->graphql_single_name}_fields", 'your_prefix_replace_term_link_resolver', 10, 1 );
         }
     }
}

Now, we’re at a point where each TermObjectType (category, tag, etc) will have its fields filtered. So now we need to alter the $fields to replace the resolver for the link field to make use of the cached function we have available in the VIP environment.

// This is the callback for our filter on the termObjectType fields. 
// We get the $fields passed to us and we want to replace the "resolve" function for the "link" field
function your_prefix_replace_term_link_resolver( $fields ) {
    if ( ! empty( $fields['link'] ) ) {
        $fields['link']['resolver'] = function( \WP_Term $term, $args, $context, $info ) {

            // Get the term link using the VIP cached function
            // You could even wrap this with a "function_exists( 'wpcom_vip_get_term_link' )" and fall back to the standard "get_term_link" function
            // to make sure things work when running in an environment where the VIP functions are not present
            $term_link = wpcom_vip_get_term_link( $term->term_id );

            // If the response was valid, return it, otherwise return a null response. 
            // You might also want to throw an exception if the response was a WP_Error
            return ( ! empty( $term_link ) && ! is_wp_error( $term_link ) ) ? $term_link : null;
        
        }
    }

   // Return the $fields, altered or not
   return $fields;
}

There we have it. We now have our link field on TermObjects resolving using a WordPress.com VIP cached function!

Now, we can execute a query like so and know that the link field will be more performant.

{
  tags{
     edges{ 
       node{
          id
          name
          link
       }
     }
  }
}

 

Query Dad Jokes with WPGraphQL

If you’ve ever wanted to use GraphQL to query dad jokes, look no further.

If you’re running a WordPress site, you can install the WPGraphQL plugin along with the WPGraphQL Dad Jokes plugin, and you can query for a random Dad Joke using GraphQL!

The plugin uses icanhazdadjoke.com to retrieve a random dad joke.

This also serves as a great example on how to extend WPGraphQL to customize the Schema for your needs.

The beauty of GraphQL is the data that resolves can come from anywhere. Even though it’s a WordPress plugin, the data that’s queried and resolved, doesn’t have to live in WordPress!

Enjoy!