Working with Gatsby's data layer

May 27, 2021

programming

Working with Gatsby's data layer

Welcome to my series on Gatsby development. I’ve been using Gatsby for about two years on and off and I find myself coming back to it whenever I need to make a new website. I want to share a few bits of learning that has been immensely helpful in understanding the capabilities of Gatsby. I will be focusing on the Gatsby data layer in this post.

GraphQL

To understand the data layer we will need to dive into the system Gatsby uses to query data. Gatsby uses GraphQL to enable components to declare the data they need. GraphQL was invented at Facebook to help product engineers pull needed data into components. It’s a query language which is what the QL part of its name stands for. It uses a type system known as the schema definition language(SDL).

Benefits of GraphQL over REST

With a REST API you typically gather the data you need for a given page by accessing multiple endpoints. For example you might use an endpoint to gather initial data /users/<id> then a second endpoint to grab all the posts /users/<id>/posts. However with GraphQL you’d only need to sed a single query to the GraphQL server that includes the concrete data requirements.

GraphQL in Gatsby enables the following:

  • Automatically optimize images for faster loading and responsiveness.
  • Allows you to create relationships with data so we don’t have to query each individual piece.
  • No more over and under fetching. One of the most common problems with REST is over and under fetching. This happens because the only way for a client to download data is hitting endpoints that return fixed data structures.
  • Myriad of source and transform plugins to source data from different data sources and formatting that in a way that can be used in your Gatsby application.

GraphQL Type System

GraphQL spec defines some built-in scaler values:

  • Int
  • Float
  • String
  • Boolean
  • ID

Lists/arrays in the type system can be denoted by square brackets: [String!]. This indicates that we are defining a list of items that are of type String and the ! indicates that this is a required field.

Example of SDL

type Post {
 id: String!
 title: String!
 publishedAt: DateTime!
 likes: Int! @default(value: 0)
 blog: Blog @relation(name: "Posts")
}

type Blog {
 id: String!
 name: String!
 description: String
 posts: [Post!]! @relation(name: "Posts")
}

Interface

An interface can be used to describe a type in an abstract way. It allows you to specify a set of fields that any concrete type which implements this interface needs to have. Below you’ll find a basic interface called Node and a type User which implements Node. Note that you need to implement all the fields present in an interface that another type inherits.

interface Node {
  id: ID!
}

type User implements Node {
  id: ID!
  name: String!
  age: Int!
}

Gatsby Data Loading

Now that you know a little bit about GraphQL and it’s SDL system. I have some good news you don’t need to go through the trouble of defining all the types that you intend to use in Gatsby.

A core feature of Gatsby is its ability to load data from anywhere to accomplish this Gatsby comes with an extensive set of plugins namely called source plugins.

Here you can view the list of available plugins. Most of the source plugins are prefixed with gatsby-source-*. These plugins allow you to source data from the filesystem, CMSs, External GraphQL servers, databases, markdown.

Along with source plugins Gatsby comes with a lot of transform plugins that allow you to change the format of the data to be used in your graphQL query.

A few commonly used transform plugins in Gatsby are

  • gatsby-transformer-sharp - used for processing your images in a variety of ways including resizing, cropping, creating responsive images, and provides a node ImageSharp to be queried in GraphQL.
  • gatsby-transformer-remark - used to parse Markdown files using Remark and provides a node allMarkdownRemark to be queried in GraphQL.
  • gatsby-transformer-json - used to parse JSON files into GraphQL nodes.

If none of these plugins suite your needs you can define your own schema in gatsby-node.js using the createTypes action. Gatsby automaticly infers

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    type AuthorJson implements Node {
      joinedAt: Date
    }
  `
  createTypes(typeDefs)
}

Gatsby automatically infers other fields in a defined type if you don’t include them from it’s source and transform plugins. if you want to be more explicit you can add @dontInfer to the type definition.

When compiling your site at build time, Gatsby preprocesses all GraphQL queries it finds and prefetches data to be available. If you need to query data at runtime on the client side you can always use the the regular React way of doing data fetching with the useEffect hook.

After all this if you still don’t want to use GraphQL with Gatsby you can still fetch data the Javascript way and still have it pre-processed at build time. By including the data in the context object in the gatsby-node.js file

 exports.createPages = async ({ actions: { createPage } }) => {
 // `getHackeNewsData` is a function that fetches our data
 const allHackerNews = await getHackeNewsData(["programming", "javascript", "startup"])
 // Create a page that lists the hacker news data.
 createPage({
   path: `/`,
   component: require.resolve("./src/templates/all-hackernews.js"),
   context: { allHackerNews },
 })
 // Create a page for each Pokémon.
 allHackerNews .forEach(article => {
   createPage({
     path: `/hackernews/${article.name}/`,
     component: require.resolve("./src/templates/hackernews.js"),
     context: { article },
   })
 })
}

After reading this article hope you’ve gotten a better understanding of the data layer of Gatsby. Thanks for stopping by and keep reading for more Gatsby content.


Profile picture

Written by Krishna Halaharvi who lives and works in Austin, TX building useful things. You should follow me on Twitter

© 2021, Krishna Halaharvi