Incremental Graphql
Quick refresher
- query language for APIs
- alternative to REST
- customizable requests
Why Graphql?
- One centralized endpoint
- Client gets exactly what it needs
- less overhead
- faster
- Typed!
This all sounds great but what about when you have tons of legacy code that uses REST
Easy APIs
- You can use tools like Prisma or Hasura to autogenerate a schema from your database models
- Hasura, for example, "auto-generates queries as part of the GraphQL schema from your Postgres schema model. It generates a range of possible queries and operators that also work with relationships defined in your SQL schema".
Mock Data
- You can mock the data that is returned from your API to get a quicker start
- As easy as setting mocks to true when you start your Apollo Server
- Or you can customize your mocks
const { ApolloServer, gql } = require("apollo-server");
const faker = require("faker");
const typeDefs = gql`
type Dog {
id: ID!
name: String!
age: Int
}
type Query {
allDog: [Dog!]!
}
`;
const mocks = {
ID: () => faker.random.uuid(),
Int: () => faker.random.number({ min: 1, max: 25 }),
String: () => faker.name.firstName(),
};
const resolvers = {
Query: {
allDogs: () => [{id: 1, name: "Meatball"}]
}
};
const server = new ApolloServer({typeDefs, resolvers, mocks, mockEntireSchema: false});
server
.listen()
.then(({ port }) => console.log(`Server running on port ${port}`));
Baby steps on the client
- You can use a regular fetch/axios/graphql-request
- Note that these will be POST requests with the query as the body
var query = `{ allBooks { title } }`;
var url = "https://books.com/graphql";
var opts = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query })
};
fetch(url, opts)
.then(res => res.json())
.then(
({ data }) => `
<p>Book of the day: ${data.Book.title}</p>
`
)
.then(text => (document.body.innerHTML = text))
.catch(console.error);
import { request } from 'graphql-request'
var url = 'https://books.com/graphql'
var mutation = `
mutation newBook($title: String! $author: String!) {
addBook(title: $title, author: $author) {
title
author
}
}
`
var variables = { title: 'Jane Eyre', author: 'Charlotte Brontë' }
request(url, mutation, variables)
.then(console.log)
.catch(console.error)
Case study: Twitch
- They built graphql on top of a REST backend at first, and then rebuilt the services with graphql instead of REST
- "Adding a GraphQL API to the ecosystem was like adding a missing unit test”
- Went from 0 to 100% graphql in a year
- Tens of REST requests -> single GraphQL request
- Start with a prototype schema
- Built out types for logged-out version our the front page (authentication is tough...)
- Client-driven approach to figure out what data to get from the GraphQL API
- Incorporated pagination with help from Relay's pagination specification
- standardized, consistent scheme
- allowed services to adopt cursor-based pagination on their own time
- Moved auth logic into services (and out of API layer)
Further reading
Incremental Graphql
By borisonr
Incremental Graphql
- 567