Part 1 – Intro to GraphQL
During my time with Lynkz I’ve had the opportunity to work with GraphQL, in this guide I’ll cover the basic principals of getting started with GraphQL.
Every developer at some point in their career used REST before to enable the frontend of their application to communicate to a backend system, while REST does the job there are other options on the market which preform similar or better. One such option that I’ll be describing in this article is GraphQL.
GraphQL was created by Facebook as they needed an API format which was powerful enough to describe the entirety of the Facebook ecosystem while also being easy to learn and to provide predictable results.
One core problem Facebook was trying to solve with this new API format was the idea that different platforms e.g Mobile and Desktop may need similar data provided from an API but each platform might need more or less of the data provided from an API and in the case of Mobile devices where users have high latency connections every bit of data transferred should be questioned.
Another problem being the amount of boiler plate code required to fetch data from multiple rest endpoints to prepare the data, parse it and then join it all together, this code then is typically rewritten for each platform as required.
GraphQL aims to solve both the above problems by allowing the developer in one HTTP query to query against multiple resources and choose what data they require, rather than in the REST format having to make a HTTP query to each resource that is required, and receiving all the data the server decides to return for that resource.
I’ll walk through the basic make up of GraphQL
In GraphQL you first describe what your data will look like through the GraphQL Schema format, this is a strongly typed “contract” where the API is described in terms of types, fields and the relationship between them, rather than endpoints in a REST API.
The GraphQL Server will only accept queries which use these fields, and won’t allow the server to return data which isn’t listed within this “contract”.
The top-level items a developer can query within GraphQL are specified under the “Type Query” block, within the above schema we can query and find a single hero by passing a character name or query against all heroes without any arguments.
The GraphQL Schema is designed to be in an easily readable format for both human and computers, this helps with onboarding new developers as they can easily see what the API represents and how to query the data, and by being easily parsed by a computer it allows a whole range of tools to extract information from the schema and present it to the user in different ways. (I talk about some of these tools later in the article)
To read more about the schema syntax see https://graphql.github.io/learn/schema/
In GraphQL the developer can query against the schema by writing a query, this query must specify each field that is required to be returned as the GraphQL server will only return the fields listed in the query, leading to an optimised predictable result.
For example, to query all hero names we could use:
Which will return the following data:
As you can see, we only received the data that was requested.
Now lets define a slightly more complicated query as GraphQL queries can traverse related objects and dive deeper down the tree defined within the schema which allows the developer to fetch multiple related resources within one GraphQL query.
For example, fetching the hero’s friends and home world:
As you can see in the above returned result the data is returned formatted into a tree of data, and only contains the fields we requested within the query, this means not only is this query efficient for slower connections, its also easier for a developer to parse the returned result.
Arguments can be passed into queries at any level not just the root level as defined in the above schema.
For example, we could modify our original schema to add arguments when a user queries the “friends” field under the Character data type.
Using the above modified schema, I could now apply pagination to the hero’s friends and only fetch their first friend.
Multiple top-level items can be queried from the GraphQL server at once in a single http call, if the same resource is requested more than once the resource will also need to be labelled a unique name within the query, for example I’m using “ironMan” and “hulk”
To read more about queries see https://graphql.github.io/learn/queries/
Mutations are GraphQL’s equivalent of a REST’s PUT/POST/DELETE in which they tell the server to perform an operation on the underlying data source.
To add a mutation, we’ll need to edit the GraphQL schema to define the operation we want “addHero” and what fields the operation accepts, and what GraphQL data structure it returns.
Now the schema has been defined, we can now make a GraphQL mutation to add a new hero into our data
As you can see above, a mutation looks similar to a query, except it needs to be contained within a “mutation” block, then we pass the data required as defined in our GraphQL schema as an argument.
For the return object we ask for the hero’s name, in a real world situation you would most likely be requesting the inserted ID but that’s the power of the GraphQL protocol the developer can decide what fields of the Character resource is needed for the platform they’re developing for.
GraphQL can also define a “subscription” type where a websocket is formed instead of a single http call, and the server can pass any updates to data through the subscription.
I’ll be talking more about this feature in future articles.
The GraphQL Server allows clients to request a copy of the GraphQL Schema without needing anything more than the endpoint URL, this allows for tools like Postman and GraphQL Playground to automatically provide intellisense to users when writing queries.
Using this data there is an entire ecosystem of tools to enable developers to easily use and visualise GraphQL queries and schemas, I’ve listed a few handy tools here.
- Graphql playground – similar to swagger for REST this tool provides the ability to query against the GraphQL server from an interactive webpage and provides documentation. This is typically packaged with most GraphQL servers https://github.com/prisma-labs/graphql-playground
- Voyager – allows the developer to visualise the entire GraphQL schema and all the relationships. https://github.com/APIs-guru/graphql-voyager
- GraphQL Code Generator – a tool which allows the developer to automatically generate code from GraphQL queries and the GraphQL Schema https://graphql-code-generator.com/ which can speed up development time as the developer doesn’t need to write as much “boiler plate” code themselves.
- Apollo GraphQL for VSCode – Provides intellisense and syntax highlighting of GraphQL queries from within VSCode. https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo
How to setup a GraphQL server (to be continued):
For C# the most popular GraphQL Server is Hot Chocolate https://hotchocolate.io/ and in a further article I’ll walk you through how to setup the Hot Chocolate GraphQL server and to configure it to automatically produce the GraphQL schema based on your C# types ( Similar to how swagger produces its documentation).