This content originally appeared on DEV Community and was authored by Salma Alam-Naylor
I’ve been using the Contentful GraphQL API pretty extensively for the past year to build a variety of projects on the Jamstack, and I got sucked in pretty quickly without really knowing much about the inner workings of GraphQL. While it’s easy to start making your first query with GraphQL with very little research, I thought it would be useful to consolidate all I’ve learned throughout the year and provide a high-level introduction to GraphQL for anyone interested in getting started.
What is an API?
API stands for Application Programming Interface, which is a way to communicate between different software services. Different types of APIs are used in programming hardware and software, including Web APIs — like the APIs that Contentful provides. If you’re new to development, I recommend you check out this blog post — What is an API? — to get a good grounding on APIs and the role they play in web development.
A brief history of GraphQL
GraphQL is a language used to communicate with backend systems, allowing you to fetch and manipulate your data. It was developed by Facebook in 2012, and released to the public in 2015. In 2019, the project was moved to the non-profit GraphQL Foundation, with a mission to ensure that the GraphQL community is able to focus on its continued evolution on a neutral platform.
What does GraphQL mean?
GraphQL is language-agnostic, which means it can be used with any backend framework or programming language, and is essentially an addition to a backend service that allows developers to communicate with the database and request data in a specific way.
To create a GraphQL server for your data source, you can use specialized tools such as ApolloGraphQL, which allow you to create a layer on top of your backend and database(s), enabling your data to be represented, queried and changed via the Graph Query Language.
And finally, GraphQL stands for “Graph Query Language.” Let’s unpack what we mean by “graph” and “query language.”
Your data, represented in a graph
GraphQL creates a representation of your data that is designed to feel familiar and natural, like a visual graph. The Oxford Learner’s Dictionary defines a graph as:
[A] diagram consisting of a line or lines, showing how two or more sets of numbers are related to each other.
The graph part of GraphQL describes a data structure of a collection of objects — or nodes — that are connected to each other through a set of links, or edges. Relationships between different objects can be represented in a user interface as a result of this graph structure. The key concept is that the data structure is non-linear, meaning that one object can be connected to more than one other object, and relationships can also be circular.
There are specialized tools available, such as GraphiQL, to represent the relationships between node types on a GraphQL API. Here’s a screenshot from another great tool — the GraphQL Playground app available in Contentful’s app marketplace — showing the relationships between data in the Contentful space that powers my personal website. Notice how you can drill down and inspect the data types in each content type, and understand how they are related to each other.
In this particular example, a blogPost
node contains an author
node, which contains an image
node, which contains a fileName
of type String. Trace the relationships down the tree by following the highlighted nodes.
Being able to inspect all types that exist in your data is a really powerful tool with predictable results to help you build robust and scalable applications. You might already be starting to realize that having this level of visibility and insight over the data structures that power your content — all within a user interface — is starting to look and feel pretty powerful if you’re a front-end developer! If you want to read more about “thinking in graphs,” have a look at this fantastic resource from graphql.org.
So that’s the graph part of GraphQL. Next, let’s take a look at the query language and how a type system ties everything together.
A type system makes things predictable
You may already be familiar with the concept of a REST API, which adopts a resource-based approach to data reading and writing, determined by the format of the API URLs over HTTP. (If you’re new to REST and you want some more context, check out this post — What is a REST API?) In contrast to REST, the GraphQL query language allows you to request data from multiple different “resources” (such as blog posts, pages, authors and anything else) in just one API call using a single URL endpoint — usually over HTTP.
When building up a web page, you may need to display different types of data in different UI components. Perhaps you might need to fetch a blog post, an author, a set of navigation links, a list of related blog posts, and so on — all for a single page. When using GraphQL, you can request all the different data types you need to build up your UIs in a single API call, instead of having to make multiple requests for different “resources.”
Here’s an example of a GraphQL query which is requesting data from four different content types (or resources) in Contentful: a blogPost
, an author
, an event
, and a talk
. Essentially, we’re requesting four different objects, and particular fields on those objects. For example, on the eventCollection
object, we’re requesting the items
field, and for each of those objects in items
, the name
field. The query is prefixed with the word query — on the GraphQL schema, a query is of type Query
!
When using a REST API, you’d need to make four different API calls to request data from these four different content types. With GraphQL, you can do it all in one go!
query {
blogPostCollection {
items {
title
author {
name
}
}
}
eventCollection {
items {
name
}
}
talkCollection {
items {
title
}
}
}
And here’s the result of the query. Notice we have all the data we requested in one response. (Note: I added limits into the query below to be able to demonstrate this in a single page view.) What’s also great about the GraphQL response object is that the object keys returned are exactly the same as we requested. This makes GraphQL predictable and intuitive to use. You get exactly what you ask for in the response — no more, no less — in the same order, with the same structure.
Use the keyboard shortcut ctrl + space when you’re building up a query in a GraphQL explorer to see the fields available to select on an object. This is a handy way to get inline hints about the schema of your data as you build up your queries — and the data type of those fields.
If you want to take a deeper dive into types in GraphQL, take a look at the official GraphQL documentation on schemas and types.
You might be thinking — how is this graph structure generated from the GraphQL schema? Let’s take a look at introspection queries.
Introspection queries expose a GraphQL schema
GraphQL comes with an introspection query system, which is a way to query the type system and data structures in your database in order to generate the documentation and provide hints in the GraphQL UI. If you’re not familiar with the word introspection, it means to look inward and examine your own state.
You can actually query your GraphQL schema using GraphQL itself! This root-level query returns all of the data types you have in your schema.
query {
__schema {
types {
name
}
}
}
You’ll see three different types of data returned in an introspection query.
- Types defined by the schema: in the case of my personal website built with Contentful, these will be types such as
BlogPost
,Asset
,Talk
,Event
,Project
and so on. - Types defined by the type of field data (scalar types): such as
String
,Boolean
. - Internal introspection query types: such as
__Schema
,__Type
,__Field
— and these are prefixed by a double underscore.
In GraphQL, each field in a query acts as a function which returns the next field type, and the next type, and the next type, until the field returned is a scalar value, such as a String or a Boolean. This is demonstrated in the example above from my personal website, where a blogPost
node contained an author
node, which contained an image
node, which contained a fileName
of type String — a scalar value — and that’s where the journey ends.
When any field is executed, a resolver is called to produce the field value. When developing your own GraphQL servers and making database changes, you’ll need to provide a resolver for each new field type you add to the API. Learn more about resolvers from GraphQL.org.
A great feature of the Contentful GraphQL API is that the GraphQL schema of your data is generated at request time, meaning it is always up to date with the current status of your Contentful space. You don’t need to worry about resolvers — we handle it for you.
If you want to find out more about introspection queries and how to watch them run in the network tab of the browser when loading up a GraphQL explorer, check out this video on the Contentful Youtube channel.
So far we’ve focused on just reading data from a GraphQL API. But writing to a database via GraphQL is also possible — and this comes with another special word — mutation.
Write data with GraphQL mutations
To mutate something means to change, or manipulate it. You can manipulate your server-side data via GraphQL using the mutation
keyword that prefixes a query. The Contentful GraphQL API is read-only, so you can’t perform mutations in Contentful using GraphQL, but in theory, here’s how it works if I wanted to create a new blog post, save the title, and return the new data in the response.
mutation CreateNewBlogPost($title: String!) {
createBlogPost(title: $title) {
title
}
}
- The query begins with the word
mutation
, and in GraphQL APIs that support mutations, this is of typeMutation
, in the same way that a read-query is of typeQuery
as described above. - Next, we need to wrap the mutation in what looks like a function, where we define the variables needed — and their types — to complete the mutation. This is CreateNewBlogPost which takes in a variable title which is of type String. The ! means that the variable is required in order for the mutation to happen. For more information on how to use variables in GraphQL, check out this blog post I wrote a little while back:
TIL: How to use GraphQL variables to give my queries type safety
Salma Alam-Naylor ・ Oct 25 ・ 6 min read
- Inside the “function,” you would use the mutation available on the GraphQL API (use introspection queries to find it!). In this case, it’s
createBlogPost
. Inside the mutation, define the variable(s) to pass in. - And finally, inside the mutation, define the fields you’d like to return in the response. In this case, I’m just creating a title, so I just want to return the new title in the response.
Make a request to the API with the mutation query and variables, and here’s the response you’ll see from the API after the mutation has completed. Again, the output is in the same recognizable format as the input!
{
"data": {
"createBlogPost": {
"title": "My new blog post title!",
}
}
}
To read more on GraphQL mutations, check out the official documentation from GraphQL.org.
So now we’ve covered how to read from (query) and write to (mutate) a GraphQL API where supported, let’s take a brief look at how we can communicate with a GraphQL API to perform those actions.
How to communicate with a GraphQL API
GraphQL is usually served over HTTP via a GraphQL server. There are other ways to communicate with GraphQL, such as via WebSockets, but HTTP is largely the most popular choice. If you’d like to read up on how to use GraphQL with cURL, Python, JavaScript, Ruby and PHP over HTTP, check out this blog post: GraphQL via HTTP in five ways.
Here’s a quick example of how to request a title and excerpt from a blog post stored in Contentful via GraphQL, using JavaScript fetch. You can make this same HTTP call using any language or framework as long as it supports HTTP!
In this example we’re sending the request via HTTP POST by sending the access token in an Authorization header and the GraphQL query in the body of the request. You can also make the same request via HTTP GET, but you’ll need to append the query and access token to the URL of the request. Read more about using HTTP POST and GET on the Contentful GraphQL API in the documentation.
// Build the GraphQL Query
const query = `{
blogPostCollection(limit: 1) {
items {
title
excerpt
}
}`;
// Send a POST request via fetch to the Contentful GraphQL URL endpoint
const response = await fetch("https://graphql.contentful.com/content/v1/spaces/{yourSpaceId}", {
method: "POST",
// Include Authorization and Content-Type HTTP headers
headers: {
Authorization: "Bearer {yourAccessToken}",
"Content-Type": "application/json",
},
// Send the GraphQL query in the body of the request
body: JSON.stringify({ query }),
}).then((response) => console.log(response.json()));
And boom, you’ve got data from a GraphQL API! Remember, GraphQL is language-agnostic, so you can read and write to a GraphQL API using any programming language or framework — as long as it supports the protocol you need, such as HTTP.
Further reading
GraphQL is a powerful way to organize how you communicate with your backend services and databases. I’ve really enjoyed exploring what’s possible with GraphQL this year, and I’m excited to dive deeper into new projects. I might even experiment with building my own GraphQL API!
To find out more about using GraphQL to get your Contentful data — including published and preview content — check out the official documentation. And if you want to explore the wonderful world of GraphQL in more detail, take a look at the official GraphQL specification and learning materials on graphql.org. Maybe it’ll inspire you to build your own GraphQL API. Happy querying!
This content originally appeared on DEV Community and was authored by Salma Alam-Naylor
Salma Alam-Naylor | Sciencx (2021-12-14T09:08:22+00:00) An introduction to GraphQL and how to use GraphQL APIs. Retrieved from https://www.scien.cx/2021/12/14/an-introduction-to-graphql-and-how-to-use-graphql-apis/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.