Power to the Front End with GraphQL
I’ve always felt like a lot of things in development get designed backwards. It’s really easy for us to get caught up in what the data is behind the scenes, and forget that the data isn’t the end goal, providing some sort of functionality to a user is the end goal. Many times I have been on a banking site and saw a table that looked like it was literally pulled straight from a SQL table in the back end, and none of the information on it served any need I would ever realistically have.
It’s design like this that made me fairly hesitant about Rest APIs when I first read about them. Don’t get me wrong, the standardization and consistency that comes with well developed Rest APIs is a wonderful thing. However the entire concept felt like it was a way for a developer to expose the data that exists, not necessarily the data that the user wants.
A common problem often occurs in these implementations of Rest APIs, and even Rest-ish APIs: a page often will need to perform several API calls to get everything it needs, many times resulting in retrieving more information than necessary. Say you need a person’s name, well you also get their date of birth, hair color, shoe size, and whatever else you have on that student resource. You end up over-querying. Even further, in order to get nested information you often will need to make subsequent API calls.
The easy answer for preventing this might be to drift away from by-the-books Rest APIs, and start developing APIs for specific purposes (the Rest-ish APIs mentioned earlier). For instance, say that you have an API that specifically returns a student’s name, the school they attend, their two parents names, and the name of their favorite Pokemon. You now are left with potentially many APIs referring to the same resource, and overall much more code to maintain. I’m sure there’s someone out there who enjoys making slight adjustments to API result models and rewriting SQL queries to fit the new model’s shape all day every day, but that’s just simply not my cup of tea.
So after writing these Rest-ish APIs for a few months, I started wondering, “what if we could make these Rest-ish APIs more dynamic… specify the properties that need to get returned”. Not surprisingly, I was not the first person to ever have this thought; It turned out that Facebook was way ahead of me on it.
GraphQL is just a query language, not a database. Just like how “SQL” is a query language, with no implications about the actual implementation. You can build a GraphQL API in .NET (we currently utilize GraphQL.NET), Java, Javascript, anything you could think of. Neo4J is a graph database that even comes with a GraphQL API in addition to its Cypher API.
A sample of a query you would simply post to a GraphQL end point:
{
student(id:9682) {
name
dateOfBirth
school {
name
address
}
parents {
name
dateOfBirth
}
favoritePokemon {
id
generation
name
}
}
}
At some point a developer defined the shape of each of those Graph Types (Person
, School
, Pokemon
), and how to traverse them (person -parents-> person[]
), but depending on how fleshed out your GraphQL application is, they did that a long while ago for some completely different page and you don’t need to ask them to do a thing to get this information in this shape via one API call.
And suddenly we are at the point where a front end developer can focus purely on making an application for what the user wants, and not worry about designing around how the data is stored/structured. The querying API is built around what the Front End wants, and not how the Back End is designed.
Just like Rest APIs, these Graph Types can pull from any data source, not just SQL. I’ve implemented SQL, Elastic Search, Blob Storage, Redis, Neo4J, In Memory sources (application configurations, for instance), and 3rd party API calls (Salesforce APIs for instance). Anything you can think of that returns data can be put behind the GraphQL layer of abstraction. And if you design it right the Front End never needs to care. You very quickly lose concerns like “We can’t get Students
and Pokemon
data at the same time, Students
are in SQL and Pokemon
are stored in a CSV hosted on Tim’s raspberry pi”.
But back to the topic, Power to the Front End.
GraphQL is more robust than it lets on at first glance. It provides a LOT of tools to give Front End developers the ability to get exactly what they want, when they want it.
First off, Parameterization. Passing arguments via query strings gets rather frustrating. Making sure everything is URL encoded and completely validated on the back can be fairly complicated and time consuming. GraphQL has all of this pre-baked in, and depending on the implementation will automatically validate any variables you pass in.
query($studentId:Int!) {
student(id:$studentId) {
name
}
}
You simply pass it a set of variables along side the query, like such:
{
studentId: 9682
}
And it will automatically expect an integer for student id, and because it has the exclamation mark it will even validate to make sure that studentId
is not null before processing the query.
Secondly, Introspection. Any application following GraphQL’s standards will be able to explore what Graph Types are available, what properties they have, how they relate to other Graph Types, any descriptions/meta data they might have. This is MOSTLY used for autocomplete in tools like GraphiQL which are used for building/testing queries, but I have found use for it in building pages that can build themselves based on what properties are available on a node.
{
__type(name:"Pokemon") {
name
fields {
name
type {
name
kind
}
}
}
}
Directives let portions of the query be conditional. This often is good when you have dynamic information showing on a page.
query($caresAboutPokemon:Boolean!,
$studentId:Int!){
student(id:$studentId) {
name
favoritePokemon @include(if: $caresAboutPokemon) {
name
}
}
}
You still need to pass in caresAboutPokemon
, but it gives a lot of control over having different data be requested without having to do awkward string building.
There’s a number of other tools native to GraphQL that (often) come pre-packed without any extra effort from the developer, I highly recommend giving them a look.
All in all, GraphQL has proven to be an extremely powerful tool, and has provided a massive amount of versatility that has made building and modifying web pages extremely simple. I’m really hoping to see this trend of making technologies be more Front End developer friendly continue.