Setting up GraphQL Code Generator with Gatsby
For my Gatsby site, I automatically generate GraphQL query types for TypeScript, with GraphQL Code Generator. This tool reads your Gatsby GraphQL schema, parses Gatsby's code for graphql
tags, then creates TypeScript type definitions for all the GraphQL queries.
Here's how you can set-up GraphQL Code Generator in your own Gatsby site.
Installing Dependencies
First, install GraphQL Code Generator CLI and plugin dependencies from npm
:
yarn add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations
Configuring the Code Generator
Get your site running locally with yarn develop
. Here's my terminal output after Gatsby works its site generation magic:
You can now view rohan-chandra-personal-website in the browser.http://localhost:8000/View GraphiQL, an in-browser IDE, to explore your site's data and schemahttp://localhost:8000/___graphqlNote that the development build is not optimized.To create a production build, use gatsby build
The ever-helpful Gatsby points us to http://localhost:8000/___graphql
. This site allows you to explore your GraphQL data and schema. Here's the important part: GraphQL Code Generator can access this same URL to access the GraphQL schema!
Next to your package.json
, create a codegen.yaml
, with the link to the schema:
overwrite: trueschema: http://localhost:8000/___graphqldocuments:- ./src/**/*.{ts,tsx}generates:./src/graphqlTypes.ts:plugins:- typescript- typescript-operationsconfig:avoidOptionals: truemaybeValue: "T"namingConvention:enumValues: "keep"# Uncomment to reformat types with prettier.# hooks:# afterOneFileWrite:# - prettier --write
Running the Code Generator
With our code generation config now set up, head to the scripts
section of package.json
. Add in:
"scripts": {"codegen": "graphql-codegen --config codegen.yaml","codegen:watch": "graphql-codegen --config codegen.yaml --watch"}
Here's the fun part. Make sure your Gatsby site is running locally with yarn develop
, then (in another terminal) run graphql-codegen
:
yarn codegen
In ./src/graphqlTypes.ts
, you'll see your generated types. Here's what the first couple of lines look like:
export type Maybe<T> = T;export type Exact<T extends { [key: string]: unknown }> = {[K in keyof T]: T[K];};
I know what you're thinking: yarn codegen
every time I write a new GraphQL query? 😢 Thankfully, with the --watch
flag (in the second script added in package.json
above), we can regenerate types whenever the code changes:
yarn codegen:watch
Examples
The code generator parses the graphql
tag and uses the query name as the type name.
Let's walk-through two examples to see this in action. You'll want yarn develop
and yarn codegen:watch
running in two terminals, if you'd like to follow along.
Static Query Hook Example
Here's an example of using the static query hook from Gatsby. I have my Gatsby site running (with yarn develop
, which makes the GraphQL schema accessible) and the code generator keeping an eye on any new code (with yarn codegen:watch
).
Create a file of ./src/pages/codegen.tsx
with the below code. Visit http://localhost:8000/codegen
to checkout your new page!
import React from "react";import { graphql, useStaticQuery } from "gatsby";import { DemoQuery } from "-/graphqlTypes";const CodegenPage: React.FC = () => {const data = useStaticQuery<DemoQuery>(graphql`query Demo {site {siteMetadata {title}}}`);return (<><p>{data.site.siteMetadata.title}</p></>);};export default CodegenPage;
Pay special attention to the query name: the generated type is DemoQuery
, as I named the query as Demo
. The generated types are in the ./src/graphqlTypes.ts
file, which is imported with:
import { DemoQuery } from "-/graphqlTypes";
Other than these two changes, the code looks like it normally would without codegen.
Page Query Example
Let's also use a page query. Again, I have my Gatsby site running with yarn develop
, while the code generator runs in the background (yarn codegen:watch
).
Create ./src/pages/codegen.tsx
with the following code:
import React from "react";import { graphql } from "gatsby";import { DemoQuery } from "-/graphqlTypes";interface Props {data: DemoQuery;}const CodegenPage: React.FC<Props> = ({ data }) => {return (<><p>{data.site.siteMetadata.title}</p></>);};export const query = graphql`query Demo {site {siteMetadata {title}}}`;export default CodegenPage;
All the concepts are the same as the hook version. DemoQuery
is generated for us as the query is named Demo
, which we can then use in our prop types. Sweet!