0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[GraphQL × Nextjs] Code Generator の活用プラクティス

Last updated at Posted at 2025-06-01

概要

本記事では Code Generator を活用した GraphQL × Nextjs の開発プラクティスについて紹介します。

Codegenとは

GraphQL Code Generator(codegen)は、GraphQLスキーマとクエリからTypeScriptの型定義を自動生成するツールです。

手動で型を書く必要がなく、GraphQLスキーマの変更に自動で追従できるため、型安全で保守性の高いアプリケーションを構築できます🙋‍♂️

セットアップ

パッケージのインストール

npm install --save-dev @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-document-nodes

codegen.yml の作成

codegen.yml
overwrite: true
schema: "http://localhost:5000/graphql"
documents: "src/**/*.graphql"
generates:
  src/generated/graphql.ts:
    plugins:
      - typescript
      - typescript-operations
      - typed-document-node
    config:
      scalars:
        ISO8601DateTime: string

package.jsonにスクリプト追加

package.json
{
  "scripts": {
    "codegen": "graphql-codegen --config codegen.yml",
    "codegen:watch": "graphql-codegen --config codegen.yml --watch"
  }
}

ワークフロー

ディレクトリ構成(推奨例)

src/
├── graphql/
   ├── queries/ # 実行するクエリファイルを格納
   │   ├── getPosts.graphql
   │   └── getPost.graphql
   ├── mutations/  # 実行するミューテーションファイルを格納
   │   ├── createPost.graphql
   │   └── updatePost.graphql
   └── generated.ts # Codegenにより生成されるファイル
# 1. GraphQLクエリファイルを作成
# 例)src/graphql/queries/getPost.graphql...

# 2. 型を生成
npm run codegen

# 3. 生成された型を使用
import { GetPostQuery, GetPostDocument } from './generated'

開発フロー

GraphQLクエリの作成

src/graphql/queries/getPost.graphql
query GetPost($id: ID!, $first: Int!) {
  published {
    post(id: $id) {
      id
      title
      content
    }
  }
}

型の生成

npm run codegen

# watch mode
npm run codegen:watch

生成された型の使用

import { GetPostDocument, GetPostQuery } from '@/generated/graphql';

export const getPost = async (id: string): Promise<GetPostQuery> => {
  const { data } = await query({
    query: GetPostDocument,
      variables: { id }
    });
 
    return data;
};

Codegenによって生成される型と活用シチュエーション

1. Document型 - [QueryName]Document

用途: GraphQLクエリの実行時に使用

// 生成例
export const GetPostDocument = ...;

// 使用シチュエーション
const { data } = await client.query({
  query: GetPostDocument, // ← 実行可能なクエリとして使用
  variables: { id: "123" }
});

2. Query型 - [QueryName]Query

用途: クエリ結果の型安全な受け取り・処理

// 生成例
export type GetPostQuery = {
  published: {
    post: {
      id: string;
      title: string;
      content: string;
    } | null;
  };
};

// 使用シチュエーション
const processPostData = (data: GetPostQuery) => {
  const post = data.published.post;
  if (post) {
    console.log(post.title); // 型安全にアクセス
  }
};

3. Variables型 - [QueryName]QueryVariables

用途: クエリ変数の型チェック

// 生成例
export type GetPostQueryVariables = {
  id: string;
};

// 使用シチュエーション
const fetchPost = async (id: string) => {
  const variables: GetPostQueryVariables = {
    id
  };
  
  return await query({ query: GetPostDocument, variables });
};

4. Mutation型 - [MutationName]Mutation

用途: Mutation結果の型安全な処理

// 生成例
export type CreatePostMutation = {
  createPost: {
    id: string;
    title: string;
    success: boolean;
  };
};

// 使用シチュエーション
const handleCreatePost = async () => {
  const result = await mutate({ mutation: CreatePostDocument });
  
  if (result.data) {
    const newPost: CreatePostMutation = result.data;
    console.log(`Created post: ${newPost.createPost.title}`);
  }
};

5. MutationVariables型 - [MutationName]MutationVariables

用途: Mutation入力値の型チェック

// 生成例
export type CreatePostMutationVariables = {
  title: string;
  content: string;
  tags?: string[];
};

// 使用シチュエーション
const createPost = async (postData: CreatePostMutationVariables) => {
  // 入力値が型チェックされる
  return await mutate({
    mutation: CreatePostDocument,
    variables: postData
  });
};

6. Fragment型 - [FragmentName]Fragment

用途: 再利用可能なデータ構造の型定義

// GraphQLフラグメント
fragment PostSummary on Post {
  id
  title
  publishedAt
}

// 生成例
export type PostSummaryFragment = {
  id: string;
  title: string;
  publishedAt: string;
};

// 使用シチュエーション
const PostCard = ({ post }: { post: PostSummaryFragment }) => (
  <div>
    <h3>{post.title}</h3>
    <time>{post.publishedAt}</time>
  </div>
);

まとめ

便利ですね 👌

型生成を開発フローに組み込み、型安全なGraphQLアプリケーションを構築しましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?