How To Use Fragments To Clean Up Your GraphQL Schemas

Originally posted on StepZen

If you've written multiple GraphQL queries before, you know that duplicated code builds up fast. Luckily, the GraphQL spec has defined Fragments to help you trim down your code, and StepZen has a tool to help you do it with speed!

Note: This tutorial assumes the prerequisite of basic GraphQL knowledge: types and queries. You can read up on them on the official specification site.

What are GraphQL Fragments?

Glad you asked! Basically, GraphQL Fragments help developers stick to the Don't Repeat Yourself principle.

According to the official spec, GraphQL Fragments are

"the primary unit of composition in GraphQL."

That means they're elemental, atomic-- you can't reduce the code further down. So using them means eliminating duplicated code.

But it's one thing to know what Fragments are in theory, and another to use them in practice. Let's get cracking!

If you want to follow along with me, you'll need a couple things.

  1. A StepZen account to access admin and API keys.
  2. A familiarity with the The Cat API (you'll need a free account to get access to the key)

Our Example Schemas

Our example schemas are three files under one folder.

breed.graphql

type Breed {
  temperament: String!
  origin: String!
  name: String
  life_span: String
  hairless: Int
  rare: Int
}

type Query {

  BreedById(id: String!): Breed
    @rest(
      endpoint: "https://api.thecatapi.com/v1/breeds/search?q=$id"
      configuration: "cat_config"
    )
  allBreeds: [Breed]
      @rest(
      endpoint: "https://api.thecatapi.com/v1/breeds"
      configuration: "cat_config"
    )
}

breed.graphql defines our Breed type as well as our two queries, BreedById and allBreeds. They retrieve data from Cat API endpoints, specified in StepZen's custom directive, @rest.

To learn more about @rest, check out our docs.

You'll notice a cat_config name on both queries' configuration specification.

This refers to the configuration defined in the next file:

config.yaml

configurationset:
  - configuration:
      name: cat_config
      Authorization: Apikey {{YOUR_CAT_CONFIG_KEY_HERE}}

config.yaml contains the information StepZen needs to connect to the Cat API.

Lastly, we have:

index.graphql

schema @sdl(files: ["breed.graphql"]) {
  query: Query
}

Opening Up the StepZen Schema Explorer

StepZen has a custom graphiQL query explorer that we can use to query the StepZen endpoint. There are all kinds of yummy features in the StepZen Schema Explorer, but today we're going to focus on the fragment button.

To open the Explorer, run stepzen start from the command line. If you've never used StepZen before, you might have to run stepzen login first and provide your credentials.

The StepZen Schema Explorer will open up in your browser! Click 'Explorer' -> select 'BreedById' and 'allBreeds' and select all the available fields. Hit the arrow button next to the StepZen logo, and you'll get your results back!

Now, since we're requesting all fields on both queries, we have an opportunity to use Fragments!

Normally, you'd have to go back into breed.graphql and write something like:

fragment breedFields on Breed {
  temperament
  origin
  name
  life_span
  hairless
  rare
}

...but that's not necessary with the StepZen query editor!
If you hover over the query name, you can see a button with ellipses, ( ... ) on it.

Click it, and you'll the see the Fragment's been generated for you, right there in the Explorer!

Now de-select all your fields on allBreeds and select BreedFragment.

Run your query again, and you'll get the exact results you need!

Notice that you can also edit your fragment by selecting and de-selecting fields:

This is super convenient because if you add a field in your schema, say, country_code, then all it takes is one click of a mouse to add it, not just to your fragment definitions, but to all your previous queries in the browser.

So adding country_code:

type Breed {
  temperament: String!
  origin: String!
  name: String
  life_span: String
  hairless: Int
  rare: Int
  country_code: String
}

Doesn't require going in and adding altnames to each query like:

query MyQuery {
  BreedById(id: "abys") {
    temperament
    rare
    hairless
    life_span
    name
    origin
    country_code
  }
  allBreeds {
    temperament
    rare
    hairless
    life_span
    name
    origin
    country_code
  }
}

fragment BreedFragment on Breed {
  temperament
  rare
  hairless
  life_span
  name
  origin
  country_code
}

All you have to do is click on country_code in your Breed fragment and this code:

query MyQuery {
  BreedById(id: "abys") {
    ...BreedFragment
    rare
  }
  allBreeds {
    ...BreedFragment
  }
}

fragment BreedFragment on Breed {
  temperament
  rare
  hairless
  life_span
  name
  origin
  country_code
}

Will auto-fill the resulting JSON alt names in each query for you:

{
  "data": {
    "BreedById": {
      "country_code": "EG",
      "hairless": 0,
      "life_span": "14 - 15",
      "name": "Abyssinian",
      "origin": "Egypt",
      "rare": 0,
      "temperament": "Active, Energetic, Independent, Intelligent, Gentle"
    }, {...} etc

Where To Go From Here

I hope you've enjoyed learning how to speed up your GraphQL coding experience!

If you're interested in StepZen's other features, you can check out our docs on our StepZen Schema Explorer. There are lots of other ways to streamline your coding experience there, including an exporter that helps you generate Apollo and Gatsby client code, a schema template exporter, and a documentation tab.

Please let us know what you're up to with StepZen! We'd love to hear about it on Discord or Twitter.

24