graphql-codegen について
TypeScript 開発者向けの GraphQL Code Generator 参照スキルで、設定、型生成、クライアント連携を扱います。GraphQL スキーマと操作ドキュメントから型安全なコードを生成するプロジェクトに適しています。
主な機能
- 01CLI の設定とコード生成
- 02クライアントプリセットと型生成
- 03TanStack Query 連携
- 04フラグメントのコロケーション
- 05複数スキーマの設定
- 06CI とウォッチモード
活用シーン
- 01スキーマと操作ドキュメントから TypeScript コードを生成
- 02GraphQL 操作用のクエリフックを生成
- 03開発中にドキュメントを監視して再生成
MCP 対応
`mcp__documentation__fetch_docs` で graphql-codegen の詳細ドキュメントを取得できると記載されています。
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill graphql-codegenインストール後、Claude Code で/graphql-codegenを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
quick-ref/client-preset.mdreact-query.mdtyped-document-node.md詳細
GraphQL Code Generator の基本知識
詳細な知識:包括的なドキュメントについては、technology に
graphql-codegenを指定してmcp__documentation__fetch_docsを使用してください。
インストール
npm install -D @graphql-codegen/cli @graphql-codegen/typescript \
@graphql-codegen/typescript-operations @graphql-codegen/client-preset
基本設定
// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'http://localhost:4000/graphql',
documents: ['src/**/*.tsx', 'src/**/*.ts'],
ignoreNoDocuments: true,
generates: {
'./src/gql/': {
preset: 'client',
config: {
documentMode: 'string',
},
},
},
};
export default config;
生成の実行
npx graphql-codegen
npx graphql-codegen --watch # Watch mode
Client プリセット(推奨)
client プリセットは、型安全な GraphQL に必要なものをすべて生成します。
// codegen.ts
const config: CodegenConfig = {
schema: 'http://localhost:4000/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./src/gql/': {
preset: 'client',
plugins: [],
presetConfig: {
gqlTagName: 'gql',
fragmentMasking: { unmaskFunctionName: 'getFragmentData' },
},
},
},
};
使用方法
import { gql } from '../gql';
import { useQuery } from '@apollo/client';
const GET_USER = gql(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
`);
function UserProfile({ id }: { id: string }) {
const { data, loading } = useQuery(GET_USER, {
variables: { id },
});
if (loading) return <Spinner />;
// data.user is fully typed
return <div>{data?.user?.name}</div>;
}
TanStack Query との統合
npm install -D @graphql-codegen/typescript-react-query
// codegen.ts
const config: CodegenConfig = {
schema: 'http://localhost:4000/graphql',
documents: ['src/**/*.graphql'],
generates: {
'./src/gql/index.ts': {
plugins: [
'typescript',
'typescript-operations',
'typescript-react-query',
],
config: {
fetcher: {
func: './fetcher#fetcher',
isReactHook: false,
},
reactQueryVersion: 5,
addInfiniteQuery: true,
},
},
},
};
フェッチャー
// src/gql/fetcher.ts
export const fetcher = <TData, TVariables>(
query: string,
variables?: TVariables
): (() => Promise<TData>) => {
return async () => {
const response = await fetch('http://localhost:4000/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${getToken()}`,
},
body: JSON.stringify({ query, variables }),
});
const json = await response.json();
if (json.errors) {
throw new Error(json.errors[0].message);
}
return json.data;
};
};
生成されたフックの使用方法
import { useGetUserQuery, useCreateUserMutation } from './gql';
function UserProfile({ id }: { id: string }) {
const { data, isLoading } = useGetUserQuery({ id });
const createMutation = useCreateUserMutation();
const handleCreate = () => {
createMutation.mutate({
input: { name: 'John', email: '[email protected]' },
});
};
if (isLoading) return <Spinner />;
return <div>{data?.user?.name}</div>;
}
フラグメントのコロケーション
// components/UserAvatar.tsx
import { gql, FragmentType, getFragmentData } from '../gql';
export const USER_AVATAR_FRAGMENT = gql(`
fragment UserAvatar on User {
id
name
avatarUrl
}
`);
interface Props {
user: FragmentType<typeof USER_AVATAR_FRAGMENT>;
}
export function UserAvatar({ user }: Props) {
const data = getFragmentData(USER_AVATAR_FRAGMENT, user);
return <img src={data.avatarUrl} alt={data.name} />;
}
// Usage in parent query
const GET_USER = gql(`
query GetUser($id: ID!) {
user(id: $id) {
id
...UserAvatar
}
}
`);
本番環境への対応
スキーマのポーリング
// codegen.ts
const config: CodegenConfig = {
schema: [
{
'http://localhost:4000/graphql': {
headers: {
Authorization: `Bearer ${process.env.GRAPHQL_TOKEN}`,
},
},
},
],
// ...
};
複数のスキーマ
const config: CodegenConfig = {
generates: {
'./src/gql/user-api/': {
schema: 'http://user-api:4000/graphql',
documents: ['src/features/user/**/*.tsx'],
preset: 'client',
},
'./src/gql/product-api/': {
schema: 'http://product-api:4001/graphql',
documents: ['src/features/product/**/*.tsx'],
preset: 'client',
},
},
};
CI/CD との統合
# .github/workflows/codegen.yml
name: GraphQL Codegen
on:
push:
paths:
- 'src/**/*.graphql'
- 'src/**/*.tsx'
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx graphql-codegen
- name: Check for changes
run: |
if [[ -n $(git status --porcelain src/gql) ]]; then
echo "Generated files changed"
exit 1
fi
パッケージスクリプト
{
"scripts": {
"codegen": "graphql-codegen",
"codegen:watch": "graphql-codegen --watch"
}
}
チェックリスト
- スキーマソースが設定されている(URL またはローカル)
- ドキュメントのパスがソースファイルと一致している
- 最適な出力のために client プリセットを使用している
- フェッチャーに認証が設定されている
- フラグメントのコロケーションパターンを採用している
- 開発時にウォッチモードを使用している
- CI で生成コードを検証している
- TypeScript の strict モードと互換性がある
このスキルを使用しない場合
- REST API の型生成(
openapi-codegenスキルを使用) - tRPC の型安全な API(
trpcスキルを使用) - GraphQL スキーマの設計(
graphqlスキルを使用) - TypeScript 以外のプロジェクト
- 型生成が不要な単純な GraphQL クエリ
アンチパターン
| アンチパターン | 問題点 | 解決策 |
|---|---|---|
| 生成ファイルを git にコミットする | マージの競合、型の陳腐化 | .gitignore に追加し、CI で生成する |
| client プリセットを使用しない | 設定が冗長になる | 最新の構成では client プリセットを使用する |
| スキーマの変更を無視する | 実行時に型が一致しなくなる | 開発中はウォッチモードで codegen を実行する |
| operationId またはクエリ名がない | 生成されるフック名の品質が低下する | すべてのクエリ/ミューテーションに名前を付ける |
| フラグメントを使用しない | コードが重複する | 再利用可能なフィールドにはフラグメントを使用する |
| 型だけを生成する | 実行時の検証が行われない | スキーマ検証と組み合わせる |
| スキーマ URL をハードコードする | 環境に依存する | スキーマソースには環境変数を使用する |
| ジェネレーターパッケージをバージョン固定しない | チーム内で出力にばらつきが生じる | ジェネレーターのバージョンを固定する |
クイックトラブルシューティング
| 問題 | 考えられる原因 | 解決策 |
|---|---|---|
| 生成に失敗する | スキーマまたはドキュメントが無効 | スキーマを検証し、GraphQL の構文を確認する |
| 生成後に型エラーが発生する | スキーマとコードが一致していない | 型を再生成し、スキーマの変更を確認する |
| 型が不足している | ドキュメントのパスがファイルと一致していない | ドキュメントの glob パターンを確認する |
| operation 名が重複している | 複数のファイルで同じクエリ名を使用している | operation 名を一意にする |
| フラグメントが見つからない | ドキュメントにフラグメントが含まれていない | ドキュメントにフラグメントファイルを含める |
| フックが生成されない | React Query プラグインを使用していない | typescript-react-query プラグインを追加する |
| "Cannot find module './gql'" | 生成処理が実行されていない | npm run codegen を実行する |
| 生成が遅い | ドキュメントが多すぎる | glob パターンを最適化し、ignoreNoDocuments を使用する |
| 型推論が機能しない | インポートパスが誤っている | 生成された gql フォルダーからインポートする |
参考ドキュメント
コメント
Markdown 対応