Skip to content

Commit c2f36d8

Browse files
authored
Add GraphQL Codemod blog post (#6910)
1 parent e93571c commit c2f36d8

File tree

1 file changed

+221
-0
lines changed
  • packages/web/docs/src/app/blog/(posts)/graphql-codemod-use-case-migrating-from-apollo-client-generated-hooks-to-client-preset

1 file changed

+221
-0
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
---
2+
title: GraphQL Codemod Use Case - Migrating from Apollo Client Generated Hooks to Client Preset
3+
description:
4+
Learn how to migrate from @graphql-codegen/typescript-react-apollo to Client Preset using a
5+
codemod. Improve type safety, reduce bundle size, and automate the migration process with ease.
6+
date: 2025-08-01
7+
authors: eddeee888
8+
tags: [graphql, graphql-code-generator, graphql-codegen, client-preset, typescript-react-apollo]
9+
---
10+
11+
import { Callout } from '@theguild/components'
12+
13+
It is now easier than ever to migrate from Apollo Client generated hooks (by
14+
`@graphql-codegen/typescript-react-apollo`) to Client Preset with our brand new GraphQL codemod.
15+
16+
## Why do you need to migrate?
17+
18+
Apollo Client v4 has a lot of interesting type overrides to serve as type-hint during development
19+
time. However, we lose these types by using the Apollo Client generated hooks.
20+
[Client Preset](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client) was created to
21+
solve this issue (and the bloated bundle size caused by the generated hooks), so it remains our
22+
recommended approach to write GraphQL operations.
23+
24+
There are lots more benefits for using Client Preset:
25+
26+
- Works with any GraphQL: Apollo Client, urql, GraphQL Request, and more.
27+
- Supports
28+
[fragment masking](https://the-guild.dev/graphql/hive/blog/unleash-the-power-of-fragments-with-graphql-codegen):
29+
Components get exactly what they declare, no surprises.
30+
- Managed experience: Code more, configure less.
31+
32+
We have created a codemod
33+
[@eddeee888/gcg-operation-location-migration](https://www.npmjs.com/package/@eddeee888/gcg-operation-location-migration)
34+
to make the migration smoother.
35+
36+
## Codemod usage
37+
38+
The codemod can be plugged easily into your Codegen config and run once during the migration.
39+
40+
### How it works
41+
42+
#### Before
43+
44+
There are two main approaches to using a `@graphql-codegen/typescript-react-apollo` setup:
45+
46+
- Index-based approach, where all hooks are generated into one file
47+
- Near-operation file approach, where hooks are generated into a file next to the consuming
48+
component
49+
50+
For example, given an operation document file like this:
51+
52+
```graphql
53+
# src/operations/User.graphql
54+
query User($id: ID!) {
55+
user(id: $id) {
56+
id
57+
name
58+
}
59+
}
60+
```
61+
62+
A generated hook/s would be generated into an index or near-operation file:
63+
64+
```ts
65+
// src/generated/types.ts
66+
export function useUserQuery(
67+
baseOptions: Apollo.QueryHookOptions<UserQuery, UserQueryVariables> &
68+
({ variables: UserQueryVariables; skip?: boolean } | { skip: boolean })
69+
) {
70+
const options = { ...defaultOptions, ...baseOptions }
71+
return Apollo.useQuery<UserQuery, UserQueryVariables>(UserDocument, options)
72+
}
73+
```
74+
75+
And, the hook is then used in a component file:
76+
77+
```tsx
78+
// src/User.tsx
79+
import { useUserQuery } from './generated/types'
80+
81+
export const User = ({ id }) => {
82+
const { data } = useUserQuery({ variables: { id } })
83+
// ...
84+
}
85+
```
86+
87+
#### After
88+
89+
After running the codemod, your component file will be updated to support the Client Preset
90+
approach!
91+
92+
```tsx
93+
// src/User.tsx
94+
import { graphql } from './gql'
95+
96+
const UserDoc = graphql(`
97+
query User($id: ID!) {
98+
user(id: $id) {
99+
id
100+
name
101+
}
102+
}
103+
`)
104+
105+
export const User = ({ id }) => {
106+
const { data } = useQuery(UserDoc, { variables: { id } })
107+
// ...
108+
}
109+
```
110+
111+
<Callout type="info">
112+
You may see type errors if Client Preset is not fully set up by this point. Read on to see how the
113+
migration process works end-to-end.
114+
</Callout>
115+
116+
### How to run the codemod
117+
118+
#### Installation
119+
120+
```sh npm2yarn
121+
npm install --save-dev @eddeee888/gcg-operation-location-migration
122+
```
123+
124+
### Updating Codegen config
125+
126+
Comment out all other Codegen `generates` blocks as they may interfere with the codemod, then add
127+
codemod config like the example below:
128+
129+
```ts
130+
// codegen.ts
131+
import { defineConfig } from '@eddeee888/gcg-operation-location-migration'
132+
import type { CodegenConfig } from '@graphql-codegen/cli'
133+
134+
const config: CodegenConfig = {
135+
schema: 'src/**/*.graphqls', // 👈 This points to your usual GraphQL schema endpoint or files.
136+
documents: 'src/**/*.graphql', // 👈 This points to your operation files.
137+
generates: {
138+
/*
139+
* 💡 Example of index file generation approach
140+
* Once migrated, you can remove this completely
141+
*/
142+
// 'src/generated/types.ts': {
143+
// plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
144+
// },
145+
146+
/*
147+
* 💡 Example of near-operation file approach
148+
* Once migrated, you can remove this completely
149+
*/
150+
// 'src/graphql/types.ts': {
151+
// plugins: ['typescript'],
152+
// },
153+
// './src/': {
154+
// preset: 'near-operation-file',
155+
// presetConfig: {
156+
// baseTypesPath: './graphql/types.ts',
157+
// extension: '.generated.ts',
158+
// },
159+
// plugins: ['typescript-operations', 'typescript-react-apollo'],
160+
// },
161+
162+
// 💡 Codemod config example
163+
// `src/` is the base path where we want to run the codemod.
164+
'src/': defineConfig({
165+
tsConfigFilePath: './tsconfig.json', // 👈 Path from project root to your project tsconfig.json (Note: not from the base path).
166+
gqlTag: {
167+
name: 'graphql', // 👈 The tag used to parse operation documents.
168+
importFrom: './gql', // 👈 The the module to import the graphql tag.
169+
importType: 'relative' // 👈 Whether `importFrom` is relative or absolute. If relative, the path from the base path to the module.
170+
},
171+
hooksImportFrom: '@apollo/client/react' // 👈 The module to import Apollo Client hooks. Use @apollo/client for older Apollo Client v3 versions.
172+
})
173+
}
174+
}
175+
176+
export default config
177+
```
178+
179+
### Running the codemod
180+
181+
Since the codemod is a Codegen preset, you can simply run Codegen to trigger it:
182+
183+
```sh npm2yarn
184+
npm run codegen
185+
```
186+
187+
If the codemod runs successfully, you should see your components file getting updated!
188+
189+
<Callout type="info">
190+
We have successfully tested the codemod on a few production repos with commonly used setup. If it
191+
does not work for your use case, please file an issue here:
192+
https://github.com/eddeee888/graphql-code-generator-plugins/issues
193+
</Callout>
194+
195+
### Setting up Client Preset
196+
197+
Now, you can make small changes to your Codegen config to be using Client Preset, then run Codegen
198+
again to wire up the migrated files!
199+
200+
```ts
201+
// codegen.ts
202+
import type { CodegenConfig } from '@graphql-codegen/cli'
203+
204+
const config: CodegenConfig = {
205+
schema: 'src/**/*.graphqls',
206+
documents: 'src/**/*.tsx', // 👈 Update this to point to your component files, where your operations have been migrated to.
207+
generates: {
208+
'src/gql/': {
209+
preset: 'client'
210+
}
211+
}
212+
}
213+
214+
export default config
215+
```
216+
217+
## Summary
218+
219+
In this blog post, we explored how to use GraphQL codemod to migrate from Apollo Client generated
220+
hooks approach to Client Preset. We hope this guide saves you time and reduces friction in your
221+
migration. Please reach out to [@eddeee888](https://x.com/eddeee888) if you encounter any issues!

0 commit comments

Comments
 (0)