GraphQL Code Generator is a powerful, open-source, plugin-based tool for streamlining your development by generating boilerplate code from a GQL schema. It can automate the generation of
- Typed Queries, Mutations and, Subscriptions for React, Vue, Angular, Next.js & Svelte, whether you are using Apollo Client, URQL or, React Query.
- Typed GraphQL resolvers, for any Node.js (GraphQL Yoga, GraphQL Modules, TypeGraphQL or Apollo) or Java GraphQL server.
- … And more!
This was my first experience with GraphQL (GQL) and the codegen tool so I'm going to start with what my situation is and how I went about installing and configuring it to serve my use case. I'll include links to additional info as I go.
My Setup
The web apps I work on are written in React and TypeScript. We recently migrated some of our servers to use GraphQL instead of REST, so naturally I turned to Apollo Client and started writing react hooks that extended the native useQuery
or useMutation
hooks in Apollo.
Example
import { gql, useQuery } from '@apollo/client';
const CHARACTERS_QUERY = gql`
query GetCharacters {
characters {
results {
name
origin {
name
}
}
}
}
`;
export default function useCharacters() {
return useQuery(CHARACTERS_QUERY);
}
This approach became a problem though because obviously the queries were not type safe and so I would need to write out all the TypeScript types, its also a pain to extend! As the application/s grow, I kept manually writing these query/mutation hooks, which became time consuming. There is however a way to use TypeScript with Apollo Client which in turn lead me to the GraphQL Code Generator.
Generating Types
Source Repo
The first step I had to take was to generate the TypeScript types from the GQL schema.
Install the generator's CLI as well as the TypeScript plugin
npm i -D @graphql-codegen/cli @graphql-codegen/typescript
Add a script to your package.json
execute the generator
scripts: {
...
"codegen": "graphql-codegen"
}
Create the config file in your root directory named codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://rickandmortyapi.com/graphql",
generates: {
"src/graphql/generated/graphql.ts": {
plugins: ['typescript'],
}
}
};
export default config;
This config will inform the generator to use the Rick & Morty API to generate a file (graphql.ts
) using the TypeScript plugin. This will result in the GQL schema being converted into basic TypeScript Types.
Generate React/Apollo Hooks
Source Repo
The next step will instruct the generator to use predefined queries (or mutations) to generate hooks that execute the queries using Apollo Client.
Install the TypeScript-Operations and TypeScript React Apollo plugins.
npm i -D @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo
Create src/graphql/documents.graphql
to store the queries to generate hooks for.
query Episodes {
episodes {
results {
episode
name
}
}
}
query Characters {
characters {
results {
name
species
}
}
}
Update the codegen.ts
file to use the above file and plugins to generate the result
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://rickandmortyapi.com/graphql",
documents: './**/*.graphql',
generates: {
"src/graphql/generated/graphql.ts": {
plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
},
config: {
withHooks: true
}
}
};
export default config;
The GQL documents
can take different patterns. However, after some experimentation, I found that for my use case its easier to just keep them all together in a .graphql
file. The config
attribute is where plugin attributes are specified. The withHooks
attribute is used by typescript-react-apollo
.
npm run codegen
Once you have run the generator again, you will see that the generated graphql.ts
file now contains hooks that execute the various query variants from Apollo based on the queries we declared, ie useEpisodesQuery
, useEpisodesLazyQuery
, useEpisodesSuspenseQuery
, etc.
Generate Hooks near operational files
As I'm sure you noticed from the source code, the app is structured with feature directories but our types and hooks are all generated in single file. However, I want the types to be in their own file to be used anywhere in the app but the documents and generated hooks must be in the feature directories where they are being used.
To achieve this, I used the Near Operation File Preset plugin. This plugin scans a directory for documents and generates the hooks files in the same location.
First install the plugin
npm i -D @graphql-codegen/near-operation-file-preset
In order to use this preset, you need to add 2 outputs to your codegen.ts
file:
- The first, is the base types, generated by typescript plugin.
- The second, is the one that is in charge of generating types per document.
import { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: '',
generates: {
'./src/types.ts': {
plugins: ['typescript']
},
'./src/': {
documents: './**/*.graphql',
preset: 'near-operation-file',
presetConfig: {
extension: '.generated.ts',
baseTypesPath: 'types.ts'
},
plugins: ['typescript-operations', 'typescript-react-apollo'],
config: {
withHooks: true
},
}
}
};
export default config;
npm run codegen
This will result in a *.generated.ts
file being created for each .graphql
in any directory under src
.
Final Thoughts
The GraphQL Code Generator is in fact a powerful tool that has simplified my development process. It has a large plugin library that supports many languages and presets and is generally well documented.
Top comments (0)