Mat Clutter's blog

How to export GraphQL fragments in GatsbyJS

July 21, 2019

GraphQL fragments can help organize and encourage reuse within our GatsbyJS page queries. However, how do you share fragments across pages and templates? Let's see with a GatsbyJS blog example.

This walkthrough assumes knowledge of GatsbyJS and its use of GraphQL for data querying. For more information on Gatsby and GraphQL fragments, visit Gatsby's GraphQL reference and GraphQL's Query docs about fragments.

In this example, our blog uses template files to build pages for posts and authors: blog-post.js and blog-author.js respectively. The blog-post.js and blog-author.js are very similar, requesting the same fields from PostsJson and AuthorsJson.

// src/templates/blog-post.js query
export const query = graphql`
  query ($id: String!) {
    post: postsJson(id: {eq: $id}) {
      title
      slug
      content
      publishDate(formatString: "MMMM DD, YYYY")
      tags
      author {
        slug
        name
        biography
      }
    }
  }
`

// src/templates/blog-author.js query
export const query = graphql`
  query ($id: String!) {
    post: authorsJson(id: {eq: $id}) {
      slug
      name
      biography
      posts {
        title
        slug
        content
        publishDate(formatString: "MMMM DD, YYYY")
        tags
      }
    }
  }
`

Seeing the similarity, we could abstract the post and author fields into GraphQL fragments that both queries could reference. The fragments would look like this:

fragment postFields on PostsJson {
  slug
  title
  content
  publishDate(formatString: "MMMM DD, YYYY")
  tags
}

fragment authorFields on AuthorsJson {
  slug
  name
  biography
}

Now that we know what fragments we want, how do we share fragments in Gatsby?

Exporting fragments in Gatsby

The Gatsby documentation talks about fragments in their GraphQL Reference:

“Fragments are a way to save frequently used queries for re-use. To create a fragment, define it in a query and export it as a named export from any file Gatsby is aware of. A fragment is available for use in any other GraphQL query, regardless of location in the project. Fragments defined in a Gatsby project are global, so names must be unique.”

Great! So what does that look like?

These exported fragments could be anywhere in our project, so we could co-locate them in one file or have them in files where they're first needed. It would be up to your team and project.

In our example, we have a central place for our fragments, a file called fragments.js in our project’s src directory.

In fragments.js, we can copy our fragments then turn them into Javascript named exports. As the quoted documentation mentioned, our fragment names are unique.

import { graphql } from 'gatsby'

export const postFields = graphql`
  fragment postFields on PostsJson {
    slug
    title
    content
    publishDate(formatString: "MMMM DD, YYYY")
    tags
  }
`

export const authorFields = graphql`
  fragment authorFields on AuthorsJson {
    slug
    name
    biography
  }
`

Gatsby exports those queries to the global scope, so those fragments are now available in any other GraphQL query in the project.

Back in our blog-post.js and blog-author.js queries, we can replace the fields with our newly shared fragments.

// blog-post.js query
export const query = graphql`
  query ($id: String!) {
    post: postsJson(id: {eq: $id}) {
      ...postFields

      author {
        ...authorFields
      }
    }
  }
`

// blog-author.js query
export const query = graphql`
  query ($id: String!) {
    author: authorsJson(id: {eq: $id}) {
      ...authorFields

      posts {
        ...postFields
      }
    }
  }
`

For the full example, see this code on Github.

Back to blog index