Organize Your GraphQL Calls with Fragments

September 30th, 2020



In my last post, I walked through how you could render components in React based on content from your CMS. In the GraphQL calls I went through as examples, I listed out all the content types I would call in Contentful. The problem with our implementation is scaling. As we add more content types, or locations where content types get referenced, we need to add more to our GraphQL calls. In this post, I wanted to show how to clean up those calls with fragments. Fragments let you break up your GraphQL calls into reusable components. We can leverage these to allow for cleaner, more scalable code.

Pre-Fragment Implementation

Our original implementation was the following:

query MyQuery { contentfulStandardPage(slug: {eq: "about-us"}) { title blocks { ... on ContentfulHeroBlock { id name title image { image { fluid { src } } } } ... on ContentfulTextBlock { id bodyContent { bodyContent } } } } }

If we start from the top and work our way down, we can see our code starts out with specifying our call for a Contentful content type we call Standard Page. We added a filter on the slug, indicating we want the "About" page. Next we get into the fields. There are only two fields we want on from the Standard Page, title and blocks. The title field is pretty self explainatory. The blocks field is where we can clean things up.

The Fragment

The way we build the fragments is exactly how we implement parts of the original GraphQL call. We separate it into a separate file. Here, we have an example using the HeroBlock:

import { graphql } from "gatsby" export const HeroBlockQuery = graphql` fragment HeroBlock on ContentfulHeroBlock { id title subtitle sys { contentType { sys { id } } } image { altText image { fluid { ...GatsbyContentfulFluid } } } }

We start off by declaring this as a fragment called HeroBlock. From there we make a regular GraphQL call for the HeroBlock. All of this is assigned to a variable we call HeroBlockQuery we set to export.

Original Call with Fragments

Now lets take that original call to get the StandardPage and replace all that code for content types with fragments:

export const pageQuery = graphql` query PageBySlug($slug: String!) { contentfulStandardPage(slug: {eq: $slug}) { blocks { __typename ... on Node { ... HeroBlock ... TextBlock } } } } `;

We are able to incorporate the fragments, and cut the number of lines in our call for content types from over twenty to two.

Final Thoughts

Hopefully these examples demonstrate the value of fragments. Any opportunity to make code cleaner and more reusable is a win. I have these and a some other example fragments in my Github gists if you want to check them out. If you have any questions or need any help with your implementation, feel free to reach out.

Black and white profile photo of David Boland

David Boland

Blogging about web, mobile, and content management systems. I am an Optimizely MVP, and a Contentful certified developer.