Search code examples
graphqlapollo-clientgraphql-jsgraphql-tag

Any notable difference between string interpolations and fragments?


Take the following queries:

import gql from "graphql-tag";

const FOO = gql` {
  foo (id: "12") {
    id
    qux {
      id
    }
  }
}

const BAR = gql` {
  BAR (id: "12") {
    id
    qux {
      id
    }
  }
}

It would be nice if we could keep the code DRY and define qux once.

I see two solutions:

  1. String interpolation, take qux out of the queries and define it a string. Here's a GitHub gist.
  2. Use fragments.

But going with #2 comes with a caveat:

If you are using fragments on unions and interfaces, you will need to use an IntrospectionFragmentMatcher

What are the benefits of using fragments?


Solution

  • The Apollo docs are a bit misleading there. Using interfaces or unions will require you to provide an IntrospectionFragmentMatcher, period. That's because an inline fragment is still a fragment. If you're querying a union or interface field, you're going to have to use a fragment per concrete type, inline or otherwise. So I wouldn't really consider this a "caveat" of utilizing fragments.

    You should generally use fragments for a couple of reasons:

    • Convention. Anyone already familiar with GraphQL will be able to look at your code and immediately grasp what's going on. Anyone contributing to your project will be able to do so more easily.
    • Additional validation. Fragments require "on" conditions that ensure they are used in the correct location. Using a fragment with the wrong field will produce a more informative error message than simply requesting the wrong field (see here for an example).
    • Better DX. Using a webpack loader or a babel plugin, you can keep your queries in separate files and import them directly, without having to import graphql-tag everywhere. Most IDEs support syntax highlighting and other goodies for GraphQL documents stored this way.

    The main benefit of using string interpolation is the ability to easily include or exclude fields conditionally. This is still possible with fragments by utilizing the @skip and @include directives, but is much more verbose.