Combine Apollo Tooling and Gatsby for Type Safety

by Denis Augsburger

Apollo Tooling is a command line tool for generating static types from a GraphQL backend. In combination with GatsbyJS it can be used to generate TypeScript definitions and validate the queries. To support a faster, safer and more reliable way to write these queries I highly recommend using the Apollo VSCode Plugin. It highlights your graphql queries and provides you with a useful autocomplete. 

gatsby-plugin-codegen

The extensibility of GatsbyJS is great. Instead of manually configure your vscode project, download your current graphql schema and generate your TypeScript definitions, you can just use the gatsby-plugin-codegen.

yarn add gatsby-plugin-codegen

Then add it in your gatsby-config.js file.

// In your gatsby-config.js
plugins: [
  // other plugins
  {
    resolve: "gatsby-plugin-codegen",
    options: {}
  }
];

It uses apollo-tooling to generate the types from your queries when you start gatsby. This is pretty convenient, because you don't need to configure any additional scripts while running gatsby.

Twteam created this plugin to improve the developer experience for ourself and other people around the world.

Download schema and generate typings

Just start gatsby and your done.

gatsby develop

More information

A config file is generated by the plugin with reasonalbe default options for gatsby and can be configured through options.

By default the file is apollo.config.js. This one is used for code generation as well as the VSCode plugin.

// apollo.config.js
module.exports = {
  client: {
    addTypename: false,
    excludes: [],
    includes: ["./src/**/*.tsx",
               "./src/**/*.ts",
               "./node_modules/gatsby-source-contentful/src/*.js",
               "./node_modules/gatsby-transformer-sharp/src/*.js",
               "./node_modules/gatsby-image/src/*.js"],
    service: {
      name: "gatsbySchema",
      localSchemaFile: "./schema.json"
    },
    tagName: "graphql"
  }
}

This config is later used by the vscode plugin for autocomplete and the type generation.

GatsbyJS uses graphql as their default tag name for their queries while apollo uses gql as their default. This is useful to distinguish between runtime queries with a different backend and gatsby queries.

Some GatsbyJS Plugins provide some global GraphQL fragments, which are used but not referenced in your queries. Therefore you need to include them in your plugin options, otherwise you will get errors like 

Unknown fragment “GatsbyImageSharpFixed”

Please open an issue or let us know if you encounter such fragments so we can add it to the default options.

Your can find your gatsby schema in the file schema.json. After some changes in your backend/schema just restart your gatsby site.

Install Apollo GraphQL VSCode Plugin

Install the plugin

ext install apollographql.vscode-apollo

Now we can enjoy the autocomplete and syntax highlighting of the apollo vscode plugin as you can see in the animated gif below.

Apollo VS Code Plugin preview Gatsby Query

Generate TypeScript Definitions from your queries

As a final step the plugin combines the donwloaded schema information and your GatsbyJS queries to create client side type definitions for TypeScript.

A new subdirectory will be created for each page and component with a GraphQL query - it is named __generated__. From there you can import your TypeScript definitions.  Tip:

type PageProps<TData> = {
 data: TData;
} & MatchRenderProps<{}>;

For your pages you can create a reusable type with a generic that can be extended for cross cutting concerns. Then you can use it as follows:

type BlogProps = PageProps<BlogPageQuery>
export const MyPage: React.FC<BlogProps> = ({data}) => {
	return ()
}
export const pageQuery = graphql`
  query BlogPageQuery {
    contentfulImages(name: { eq: “testImage” }) {
      id
      description   
    }
  }
`

In your components you can also use the generic version directly.

const data = useStaticQuery<TestPageQuery>(
  graphql`
    query TestPageQuery {
      contentfulImages(name: { eq: "testImage" }) {
        id
        description
        name
        fluid(maxWidth: 1000) {
          ...GatsbyContentfulFluid
        }
      }
    }
  `
)

Type Safe GatsbyJS project with apollo code generation

Current limitations

  • (We haven't experienced that anymore) In some cases we experienced that the schema.json file is not correctly reloaded into the Apollo VS Code Plugin after some changes. Therefore a restart of VS Code is necessary
  • The null checks can be extensive, so better introduce some helper function to get the related data
  • With strict null checks you can't use the contentful images in gatsby images because of the different handling of null and undefined

Denis is a passionate software engineer with many years of experience in web development. He's specialized in programming with React, GraphQL, GatsbyJS and TypeScript. In his articles he writes about working with these technologies and enjoys to share opportunities and challenges with the community.