WordPress, GraphQL & Gatsby

10up Lunch & Learn
Nov 2019

Who Am I?

What We'll Go Over

  • Why WordPress + GraphQL
  • Installing and Using the WPGraphQL Plugin
  • WordPress as an Application Data Graph
  • Efficient Data Fetching with GraphQL
  • WPGraphQL + Gatsby
  • What's next?

Why WordPress + GraphQL?

Personal Story

  • Distributed WordPress Installs
  • Content Syndication
  • Micro-apps that can interact with any number of WordPress installs

Frustrations with REST

  • Implicit requests are difficult for long-term code maintenance
  • Constant over/under-fetching
    • Unnecessarily moving tons of data over the wire
  • So many requests needed to READ / WRITE the data needed to syndicate

https://denverpost.com/wp-json/wp/v2/posts?per_page=100

Frustrations with REST

(still)

 

  • Implicit requests are difficult for long-term code maintenance
  • Constant over/under-fetching
    • Unnecessarily moving tons of data over the wire
  • So many requests needed to READ / WRITE the data needed to syndicate
  • Poor performace
    • We wanted REST to provide everything so any client could have what they needed
    • Wrapping a non-performant REST API with GraphQL === non-performant GraphQL API

WPGraphQL is a free, open-source WordPress plugin that provides an extendable GraphQL schema and API for any WordPress site.

Adding the Plugin to WordPress

Install & Activate the Plugin

Posts

Pages

Users

Comments

Terms

Media

GraphQL

{
     viewer {
          name
     }
}

{

     data: {

          viewer: {

               name: "Jason Bahl"

          }

     }
}

GraphQL Query

GraphQL Result

Post

Category

Category

Category

Post

title

"Hello World"

title

"GoodBye Mars"

Image

Image

Image

name

"news"

name

"crime"

name

"sports"

Image

WordPress as an Application Data Graph

GraphQL

GraphQL lets us pick trees out of the Application Data Graph

GraphQL

query {
  post(id: "cG9zdDox") {
    title
    link
    categories {
      nodes {
        name
      }
    }
  }
}
{
  data: {
    post: {
      title: "Hello World!"
      link: "http://site.com/hello-world"
      categories: {
        nodes: [
          {
            name: "sports"
          },
          {
            name: "crime"
          }
        ]
      }
    }
  }
}

Post

Category

Category

Category

Post

title

"Hello World"

title

"GoodBye Mars"

Image

Image

Image

name

"news"

name

"crime"

name

"sports"

Image

Demo Time!

Comparing APIs

Comparing APIs

Data Requirements:

  • List of posts
  • author
    • name
    • avatar (size: 50)
      • url
  • site
    • name
    • link
  • followLink
  • title
  • featuredImage (width: 300)
    • url
  • excerpt

Comparing APIs

<?php
$posts = new WP_Query( 
    array(
        'post_type' => 'post',
        'posts_per_page' => 4,
        'post_status' => 'publish'
    ) 
);

# Loop through the posts
<?php
# Author Data
$author = get_the_author();
$author_name = $author->display_name;
$avatar = get_avatar_data( $author->ID );
$avatar_url = $avatar->url;
# Site Info
$sites = wp_get_post_terms( 
    $post->ID, 'sites' 
);
$site_name = $sites[0]->name;
$site_link = get_term_meta( 
    $sites[0]->term_id, 
    'link', 
    true 
);
# Follow Link
$follow_link = your_follow_link_func();
# Title
$title = get_the_title();
# Featured Image
$img = get_the_post_thumbnail_url( 
    $post->ID, 
    array( 300 ) 
);
# Excerpt
$excerpt = get_the_excerpt();

Comparing APIs

# Posts

# Assumes follow link is a registered
# field on the post endpoint

HTTP GET 
/wp-json/wp/v2/posts?per_page=4

$posts.map((post) => {
    $title = post.title;
    $excerpt = post.excerpt;
    $follow = post.followLink;
});
# Authors

HTTP GET 
/wp-json/wp/v2/user/{posts[0].author}
/wp-json/wp/v2/user/{posts[1].author}
/wp-json/wp/v2/user/{posts[2].author}
/wp-json/wp/v2/user/{posts[3].author}
/wp-json/wp/v2/user/{posts[0].author}/avatar
/wp-json/wp/v2/user/{posts[1].author}/avatar
/wp-json/wp/v2/user/{posts[2].author}/avatar
/wp-json/wp/v2/user/{posts[3].author}/avatar
# Sites 

# Assumes REST API was customized to show
# The "Sites Custom Taxonomy" IDs on the 
# Post endpoint

HTTP GET 
/wp-json/wp/v2/site/{posts[0].sites[0]}
/wp-json/wp/v2/site/{posts[1].sites[0]}
/wp-json/wp/v2/site/{posts[2].sites[0]}
/wp-json/wp/v2/site/{posts[3].sites[0]}
# Featured Images

HTTP GET
/wp-json/wp/v2/media/{posts[2].featured_media}
/wp-json/wp/v2/media/{posts[3].featured_media}

Comparing APIs

            
 query { 
  posts(first: 4) {
    edges {
      node {



        














      }
    }
  }
}
            
        
            
        author {
       name
       avatar(size: 50) {
         url
       }
     }

            
        
            
                        followLink

            
        
            
                        title

            
        
            
                        featuredImage(width: 300) {
   url
}

            
        
            
                        excerpt

            
        
            
        site {
       name
       link
     }

            
        

Data Requirements:

  • List of posts
  • author
    • name
    • avatar (size: 50)
      • url
  • site
    • name
    • link
  • followLink
  • title
  • featuredImage (width: 300)
    • url
  • excerpt

Efficient Data Fetching

Solving the N+1 Problem

WPGraphQL Roadmap & v1.0

WPGraphQL Roadmap & v1.0

  • Address any predictable breaking changes
  • Nesting 1-to-1 Connections
  • Revisions / Preview Support
  • Better Interface implementation/support
  • Content connection (Query posts of any Post Type)
  • Security Audit

Gatsby Source WPGraphQL

Enable you to do the same things you do with WordPress today, but better

Gatsby Source WPGraphQL

  • Deprecate Gatsby Source WordPress (WP REST API)
  • Template Hierarchy
  • Routing
  • Search
  • Preview
  • Efficient Caching (fast rebuilds)
  • Live Data Updates (Instant rebuilds)*

WordPress, GraphQL & Gatsby - 10up

By Jason Bahl

WordPress, GraphQL & Gatsby - 10up

GraphQL for WordPress

  • 1,188