Evolving WordPress

with GraphQL

WordCamp US 2017

Jason Bahl | @jasonbahl

https://slides.com/jasonbahl-1/wcus-wordpress-graphql

Me.

  • Senior WordPress Engineer at Digital First Media in Denver, CO
  • Denver native
  • WordPress Developer for 9+ years
  • I love WordPress, and Open Source in general
  • Creator & maintainer of WPGraphQL

Who is Digital First Media?

Talk to us, we're hiring!

This Talk.

  • Evolution of the Web & WordPress
  • Evolution of WordPress APIs
  • GraphQL: The next WordPress API
  • What is GraphQL?
  • Compare GraphQL with existing WordPress APIs
  • How to use GraphQL with WordPress
  • What's Next?

Evolution of the Web

Evolution of the Web

Evolution of the Web

Evolution of the Web

Evolution of the Web

Evolution of the Web

Evolution of WordPress

BLOG

CMS

APPLICATION PLATFORM

Admin

Front End

Evolution of WordPress APIs

Evolution of WordPress APIs

BLOG

CMS

Platform

  • Plugin API
  • Theme API
  • Filesystem API
  • Database API
  • Widgets API
  • Custom Post Type API
  • Custom Taxonomy API
  • Nav Menu API
  • Rewrite API
  • Transients API
  • Settings API
  • Customizer API
  • REST API
  • What's next?

Evolution of WordPress APIs

The next WordPress API?

GraphQL

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools

GraphQL

A Query Language for your API

GraphQL

Open Source Specification

Created & maintained by Facebook

Used in production by Facebook since 2012

GraphQL

Graph != Graph Databases

Graph != Graph Search

Graph = Application Data Graph

QL = Query Language

GraphQL: A Query Language for Your Application Data Graph

GraphQL

{
     me {
          name
     }
}

{

     data: {

          me: {

               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: "...") {
    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

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

Observed Pain Points

Completely different experience using PHP and REST

# WordPress, PHP with WPGraphQL Active

$query = '
{
    posts {
        edges {
            node {
                id
                title
                link
            }
        }
    }
}
';

$data = do_graphql_request( $query );
# JavaScript, using Fetch
const query = `{
    posts {
        edges {
            node {
                id
                title
                link
            }
        }
    }
}
`;

fetch('site.com/graphql', {
    method: "POST", 
    body: {
        query: query
    }
});

Similar experience using GraphQL in PHP, or any other language

<?php
# Author Data
if ( $posts->have_posts() ) {
    while ( $posts->have_posts() ) {
        $posts->the_post();
       
        $author = get_the_author();
        $author_name = $author->display_name;
        $avatar = get_avatar_data( 
            $author->ID 
        );
        $avatar_url = $avatar->url;
    }
}
# Author Data
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
# CURL

$ curl -XPOST
  -H "Content-Type:application"
  -d '{"query":"{
      posts{
          edges{ 
              node{ 
                  id
                  title
                  link
              }
          }
      }
  }"}'
  http://site.com/graphql

Observed Pain Points

Lots of Functions / HTTP Requests

HTTP GET 
/wp-json/wp/v2/posts?per_page=4
/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
/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]}
/wp-json/wp/v2/media/{posts[2].featured_media}
/wp-json/wp/v2/media/{posts[3].featured_media}
<?php
$posts = new WP_Query( 
    array(
        'post_type' => 'post',
        'posts_per_page' => 4,
        'post_status' => 'publish'
    ) 
);
if ( $posts->have_posts() ) :
    while( $posts->have_posts() ) :
        $posts->the_post();

        $author = get_the_author();
        $author_name = $author->display_name;
        $avatar = get_avatar_data( $author->ID );
        $avatar_url = $avatar->url;

        $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 = your_follow_link_func();

        $title = get_the_title();

        $img = get_the_post_thumbnail_url( 
            $post->ID, 
            array( 300 ) 
        );

        $excerpt = get_the_excerpt();

    endwile;
endif;

Single GraphQL Request

# WordPress, PHP with WPGraphQL Active

$query = '
{
    posts {
        edges {
            node {
                id
                title
                link
            }
        }
    }
}
';

$data = do_graphql_request( $query );
  • Constantly over fetching and under fetching
  • Lots and lots of HTTP requests
  • Tight client-server coupling
  • Implicit Requests Make Maintenance Difficult
  • Maintaining Documentation
  • Versioning is difficult
  • Fetch exactly what you need, nothing more, nothing less
  • Multiple resources in a single HTTP request
  • Decoupled client-server relationship
  • Explicit requests ease maintenance
  • Self Documenting Schema / Type System
  • Easy, pain free versioning

How to use GraphQL with WordPress

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

We have stickers!

Adding the Plugin to WordPress

Install & Activate the Plugin

DEMOS

Contributors

WPGraphQL in the Wild

WPGraphQL

Evolving WordPress with GraphQL - WordCamp US 2017

By Jason Bahl

Evolving WordPress with GraphQL - WordCamp US 2017

  • 2,591